[Swift 문법] - Class

sun02·2021년 7월 17일
0

100 days of Swift 

목록 보기
9/40

1. Creating your own classes

클래스는 프로퍼티와 매서드를 가진 새로운 타입을 만든다는 점에서 구조체와 유사하지만 다섯가지 중요한 차이점을 가진다.

첫번째 차이점은 클래스에는 멤버별 이니셜라이저가 없다는 것이다.

class Dog {
    var name: String
    var breed: String

    init(name: String, breed: String) {
        self.name = name
        self.breed = breed
    }
}
  • 따라서 만약 클래스가 프로퍼티를 가진다면 항상 이니셜라이져를 만들어야 한다는 뜻이다.
let puppy = Dog(name: “Poppy”, breed: “Poodle”)
  • 클래스의 인스턴스를 만드는 것은 구조체일때와 같다.

2. Class inheritance

두 번째 차이점은 이미 존재하는 클래스를 기반으로 새로운 클래스를 만들 수 있다는 것이다 – 새로 만들어진 클래스는 원래 있던 클래스의 프로퍼티와 매서드를 모두 상속받고 그 위에 자체 프로퍼티와 매서드를 추가할 수 있다.

class Dog {
    var name: String
    var breed: String

    init(name: String, breed: String) {
        self.name = name
        self.breed = breed
    }
}
  • 위에서 방금 만든 Dog 클래스이다.
class Poodle: Dog {

}
  • 위의 Dog 클래스를 기반으로 Poodl이라는 새로운 클래스를 생성할 수 있다. Poodle은 기본적으로 Dog의 프로퍼티와 이니셜라이져를 상속 받는다.

그러나 Poodle만의 이니셜라이저를 만들 수도 있다.
“Poodle” 이라는 품종을 항상 가질 것이라는 것은 알고 있기 때문에
name 프로퍼티만 필요로하는 새로운 이니셜라이져를 만들 수 있다.

class Poodle: Dog {
    init(name: String) {
        super.init(name: name, breed: “Poodle”)
    }
}
  • 다음과 같이 Poodle의 이니셜라이져가 Dog의 이니셜라이져를 바로 호출하여 모든 동일한 설정이 발생하도록 할 수 있다는 것이다.

보안상의 이유로, 스위프트는 자식 클래스에서는 항상 super.init()을 호출하도록 한다. – 자식 클래스가 생성될 때 부모 클래스가 중요한 작업을 할 경우를 대비하는 것이다.

3. Overriding methods

자식 클래스들은 부모 클래스의 매서드를 자체 구현으로 대체할 수 있다. – overriding(재정의)라고 알려진 과정이다.

class Dog {
    func makeNoise() {
        print(“Woof!”)
    }
}
  • makeNoise() 매서드를 가지는 Dog 클래스이다.
class Poodle: Dog {

}

let puppy = Poodle()
puppy.makeNoise()
  • Dog를 상속받는 새로운 Poodle 클래스를 만든다면, Poodle 클래스는 makeNoise 매서드를 상속받기에 “Woof!”를 출력한다.

매서드 재정의로 Poodle 클래스의 makeNoise() 의 실행을 바꿀 수 있다.

class Poodle : Dog {
    override func makeNoise() {
        print(“Yip!”)
    }
}
  • Swift는 매서드를 재정의 할 때 func 만 작성하기 보다 override func 로 작성하도록 요구한다. – 매서드를 실수로 재정의하는 것을 막고 부모 클래스에서 존재하지 않는 것을 재정의하려고 하는 것을 막는다.

이 변화로 puppy.makeNoise() 는 “Woof!”가 아니라 “Yip!” 를 출력할 것이다.

4. Final classes

클래스 상속이 매우 유용하더라도 – 실제로 Apple platform의 많은 부분에서 클래스를 사용하도록 요구한다
때로는 다른 개발자가 네가 만든 클래스를 기반으로 자신의 클래스를 빌드하는 것을 허용하고 싶지 않을 수도 있다.

Swift는 이를 위해 final 키워드를 제공한다
이는 네가 설정한 실행을 바꾸기 위해 너의 매서드를 재정의 할 수 없다는 뜻이다.
그들은 너의 클래스를 작성된 방식으로만 사용해야한다.

final class Dog {
    var name : String
    var breed: String

    init(name: String, breed: String) {
        self.name = name
        self.breed = breed
    }
}
  • 다음과 같이 앞에 final 키워드만 넣으면 너의 클래스는 재정의 될 수 없다.

5. Copying objects

세 번째 차이점은 복사되는 방식이다.

  • 구조체를 복사하면 기존 구조체와 복사된 구조체는 서로 다른 것이다하나를 변경시키는 것이 다른 하나에 영향을 미치지 않는다.
  • 클래스를 복사하면, 기존 클래스와 복사된 클래스는 서로 같은 것을 가리키기 때문에 하나를 변경시키면 다른 하나도 변경된다.
class Singer {
    var name = “Taylor Swift”
}
  • 디폴트 값을 가지는 name 프로퍼티를 가지는 Singer 클래스이다.
var singer = Singer()
print(singer.name)
  • 이 클래스의 인스턴스를 만들고 이름을 출력하면, “Taylor Swift” 를 받을 것이다.
var singerCopy = Singer()
singerCopy.name = “Justin Bieber”
  • 이제 두 번째 변수를 만들고 이름을 바꿔보자
print(singer.name)
  • singer와 singerCopy는 둘 다 메모리상에서 같은 객체를 가르키고 있기 때문에 다시 singer의 이름을 출력하면 “Justin Bieber”를 받을 것이다.
struct Singer {
    var name = “Taylor Swift”
}
  • 하지만 만약 Singer가 구조체였다면 두 번째로 출력할 때 우리는 “Taylor Swift”를 받을 것이다

6. Deinitializers

클래스와 구조체의 네 번째 차이점은 클래스는 Deinitializer를 가진다는 것이다 – 클래스의 인스턴스가 파괴되었을 때 실행되는 코드이다.

class Person {
    var name : String
    
    init() {
        print(“\(name) is alive!”)
    }

    func printGreeting() {
        print(“Hello, I’m \(name)!”)
    }
}
  • name 프로퍼티와 간단한 이니셜라이져, 메세지를 출력하는 printGreeting 매서드를 가지는 Person 클래스이다.
for _ in 1…3 {
    let person = Person()
    person.printGreeting()
}
  • 우리는 루프 안에 Person 클래스의 인스턴스를 여러 개 만들 것이다. 왜냐하면 루프가 돌아갈 떄마다 새로운 person이 생성되고 파괴될 것이기 때문이다.
deinit {
    print(“\(name) is no more!”)
}
  • deinitializer는은 Person 인스턴스가 파괴될 때 호출된다

7. Mutability

클래스와 구조체 간의 마지막 차이점은 상수를 다루는 방식이다.
만약 변수 프로퍼티를 가지는 상수 구조체라면 구조체가 상수기 때문에 그 프로퍼티는 변경될 수 없다.

그러나, 만약 변수 프로퍼티를 가지는 상수 클래스라면, 그 프로퍼티는 변경될 수 있다.
이 때문에 클래스는 프로퍼티를 변경시키는 매서드에 사용하는 mutating 키워드가 필요 없다; 이것은 구조체에서만 필요로 한다.

class Singer {
    var name: “Taylor Swift”
}

let taylor = Singer()
taylor.name = “Ed Sheeran”
print(taylor.name)
  • 클래스가 상수로 만들어졌더라도 클래스의 변수 프로퍼티를 변경시킬 수 있기 때문에 이것은 완벽히 유효한 코드다.
class Singer {
    let name = “Taylor Swift”
}
  • 만약 이런 변화가 생기는 것을 막고 싶다면 프로퍼티를 상수로 만들면 된다.

출처

0개의 댓글