본문 바로가기
Development

A Swift Tour: Objects and Classes

by Dev Arthur 2023. 7. 13.

<Objects and Classes>

  • Use class followed by the class’s name to create a class.
    = 'class' 뒤에 클래스 이름을 사용을해서 클래스를 만들 수 있다
  • A property declaration in a class is written the same way as a constant or variable declaration, except that it’s in the context of a class.
    = 클래스에서 프로퍼티 선언은 클래스의 문장 안에 있다는 것을 제외하고는 상수나 변수 선언과 같은 방식으로 작성된다
  • Likewise, method and function declarations are written the same way.
    = 메소드와 함수 선언도 같은 방식이다
  • ex)
class MyClass {
	let plusNumber = 1
    func plus(num: Int) -> Int{
    	return num + plusNumber
    }
}
  • Create an instance of a class by putting parentheses after the class name.
    = 클래스 이름 뒤에 괄호를 사용해서 클래스의 인스턴스를 만들 수 있다
  • Use dot syntax to access the properties and methods of the instance.
    = 그 인스턴스의 프로퍼티나 메소드에 접근하기 위해 마침표 문법을 사용한다
  • ex)
var myInstance = MyClass()
print(myInstance.plusNumber) // 1
print(myInstance.plus(num: 11)) // 12
  • This version of the MyClass class is missing something important: an initializer to set up the class when an instance is created.
    = 위 MyClass 클래스는 중요한 것이 빠졌다: 인스턴스가 생성되었을때,  클래스를 설정하는 initializer
  • ex)
class MyClass {
	var myNumber : Int
	let plusNumber = 1
    
    init(myNumber: Int){
    	self.myNumber = myNumber
    }
    
    func plus(num: Int) -> Int{
    	return num + plusNumber
    }
}
  • Notice how self is used to distinguish the myNumber property from the myNumber argument to the initializer.
    = self는 프로퍼티인 myNumber와 인수인 myNumber를 구별하기 위해 사용한다
  • The arguments to the initializer are passed like a function call when you create an instance of the class.
    = 이니셜라이저의 인수는 클래스의 인스턴스를 만들었을때, 함수 호출하는 것처럼 전달된다(매개변수가 있는 함수를 호출하듯)
  • Every property needs a value assigned — either in its declaration (as with plusNumber) or in the initializer (as with myNumber).
    = 모든 프로퍼티는 값이 할당되어야한다 - plusNumber처럼 클래스를 선언할 때나, myNumber처럼 이니셜라이저를 통해
  • Use deinit to create a deinitializer if you need to perform some cleanup before the object is deallocated.
    = 만약 객체가 할당 해제되기 전에 정리작업이 필요하다면, deinitializer를 만들기 위해 deinit을 사용한다
  • Subclasses include their superclass name after their class name, separated by a colon.
    = 하위클래스는 그 클래스의 이름 뒤에 콜론(:)으로 구분지어 그 클래스의 상위클래스를 포함한다
  • There’s no requirement for classes to subclass any standard root class, so you can include or omit a superclass as needed.
    = 클래스가 모든 표준 루트 클래스를 서브클래스화 할 필요는 없기 때문에 필요에 따라 상위클래스를 포함하거나 제거할 수 있다
  • Methods on a subclass that override the superclass’s implementation are marked with override — overriding a method by accident, without override, is detected by the compiler as an error.
    = 상위클래스에서 구현된 것을 재정의한 하위클래스의 메소드는 'override'로 표시되고,  
    실수로 
    'override' 표시 없이 메소드를 재정의하면 컴파일러가 오류로 감지한다

Overriding declaration requires an 'override' keyword

  • ex)
class Circle : NamedShape {
    var radius: Double
    
    init(radius: Double, name: String){
        self.radius = radius
        super.init(name: name)
    }
    
    func area() -> Double{
        return self.radius * 3.14
    }
    
    override func simpleDescription() -> String {
        return "A circle with radius \(radius)"
    }
}
  • In addition to simple properties that are stored, properties can have a getter and a setter.
    = 저장된 단순 프로퍼티 외에도, 프로퍼티는 getter와 setter를 가질 수 있다
  • ex)
class Circle : NamedShape{
    var radius: Double
    
    init(radius: Double, name: String){
        self.radius = radius
        super.init(name: name)
    }
    
    var round: Double{
        get{
            return radius * 3.14
        }
        set{
            radius = newValue / 3.14
        }
    }
    
    func area() -> Double{
        return self.radius * 3.14
    }
    
    override func simpleDescription() -> String {
        return "A circle with radius \(radius)"
    }
}

let circle : Circle = Circle(radius: 3.0, name: "circle")
print(circle.radius) // 3.0
print(circle.round) // 9.14 (get)
circle.round = 314 // (set)
print(circle.radius) // 100

* getter/setter를 구현한 프로퍼티를 호출하면 get, 프로퍼티에 값을 대입하면 set이 되는 형식인 것 같다

  • In the setter for round(my getter/setter property), the new value has the implicit name newValue. You can provide an explicit name in parentheses after set.
    = 내가 구현한  getter/setter 프로퍼티의 setter에서 새로운 값은 암묵적으로 'newValue'라는 이름을 갖지만, 'set' 뒤에 괄호를 사용해서 명시적인 이름을 제공할 수 있다
  • ex) 
...

var round: Double{
        get{
            return radius * 3.14
        }
        set(newRadius){
            radius = newRadius / 3.14
        }
    }
    
 ...
  • Notice that the initializer for the Circle class(my class) has three different steps:
    = 위에서 내가 만든 클래스의 초기화는 3가지 단계가 있다
    1. Setting the value of properties that the subclass declares.
    = 하위클래스가 선언한 프로퍼티들의 값을 설정
    2.
    Calling the superclass’s initializer.
    = 상위클래스의 초기화(구문)을 호출
    3. Changing the value of properties defined by the superclass. Any additional setup work that uses methods, getters, or setters can also be done at this point.
    = 상위클래스에서 정의된 프로퍼티의 값을 바꾸고, 메소드/getter/setter를 사용하는 추가적인 설정 작업도 이때 진행할 수 있다
  • If you don’t need to compute the property but still need to provide code that’s run before and after setting a new value, use willSet and didSet.
    = 만약 프로퍼티를 계산할 필요는 없지만 새로운 값을 설정하기 전과 후에 실행되는 코드를 제공해야한다면, 'willSet'과 'didSet'을 사용해라
  • The code you provide is run any time the value changes outside of an initializer.
    = ('willSet'과 'didSet'을 사용한) 코드는 값이 초기화 구문의 외부에서 값이 바뀔 때마다 실행된다
  • For example, the class below ensures that the side length of its triangle is always the same as the side length of its square.
    = 예를 들어, 다음 클래스는 클래스의 삼각형 변의 길이가 클래스의 사각형의 변의 길이와 항상 같다는 것을 보장한다
class TriangleAndSquare {

    var triangle: EquilateralTriangle {
        willSet {
        	print("triangle willSet called")
            square.sideLength = newValue.sideLength
        }
    }
    
    var square: Square {
        willSet {
            print("square willSet called")
            triangle.sideLength = newValue.sideLength
        }
    }
    
    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
    
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
print(triangleAndSquare.square.sideLength) // 10.0
print(triangleAndSquare.triangle.sideLength) // 10.0
triangleAndSquare.square = Square(sideLength: 50, name: "larger square") // square willSet called
print(triangleAndSquare.triangle.sideLength) // 50.0 (그런데, "triangle willSet called"은 출력되지 않음)

* Square의 willSet이 호출되면서 "square willSet called"이 출력되고 square의 sideLength가 변경되었지만,
"triangle willSet called"은 출력되지 않았으나 Triangle의 sideLength가 변경되었다
Square의 willSet은 직접 호출되었기에 출력되었지만, Triangle의 willSet은 직접 호출된 것이 아니기에 출력되지 않고
Square의 willSet의 호출에 의해 간접적으로 Triangle의 sideLength가 변경된 것 같다

  • When working with optional values, you can write ? before operations like methods, properties, and subscripting.
    = 옵셔널 값으로 작업할 때, 메소드/프로퍼티/서브스크립트와 같은 동작 전에 "?"를 사용할  수 있다
  • If the value before the ? is nil, everything after the ? is ignored and the value of the whole expression is nil.
    = 만약 "?" 앞의 값이 nil이라면, "?" 뒤의 모든 것들은 무시되고 전체 표현식의 값은 nil이다
  • Otherwise, the optional value is unwrapped, and everything after the ? acts on the unwrapped value.
    = 그렇지 않으면("?" 앞의 값이 nil이 아니면) 옵셔널 값은 언래핑되고,  "?" 뒤의 모든 것들은 언래핑된 값으로 작동한다
  • In both cases, the value of the whole expression is an optional value.
    = 이 경우 모두, 전체 표현식의 값은 옵셔널 값이다
  • ex)
let nilValue: Int?  = nil
let notnilValue: Int? =  0

let optionalNil: Int? = nilValue
let optionalNotNil: Int? = notnilValue

optionalNil?.signum() // optionalNil 값이 nil이기에 ? 이후는 무시된다
optionalNotNil?.signum() // optionalNotNil가 nil이 아니기에 ? 이후는 언래핑된 값으로 진행된다
반응형

'Development' 카테고리의 다른 글

Homebrew 설치하기  (0) 2024.02.15
A Swift Tour: Enumerations and Structures  (0) 2023.07.20
A Swift Tour: Functions and Closures  (0) 2023.04.25
Xcode 설치하기  (0) 2023.04.13
A Swift Tour: Control Flow  (0) 2023.04.10