클래스는 프로퍼티와 매서드를 가진 새로운 타입을 만든다는 점에서 구조체와 유사하지만 다섯가지 중요한 차이점을 가진다.
첫번째 차이점은 클래스에는 멤버별 이니셜라이저가 없다는 것이다.
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”)
두 번째 차이점은 이미 존재하는 클래스를 기반으로 새로운 클래스를 만들 수 있다는 것이다 – 새로 만들어진 클래스는 원래 있던 클래스의 프로퍼티와 매서드를 모두 상속받고 그 위에 자체 프로퍼티와 매서드를 추가할 수 있다.
class Dog {
var name: String
var breed: String
init(name: String, breed: String) {
self.name = name
self.breed = breed
}
}
class Poodle: Dog {
}
그러나 Poodle만의 이니셜라이저를 만들 수도 있다.
“Poodle” 이라는 품종을 항상 가질 것이라는 것은 알고 있기 때문에
name 프로퍼티만 필요로하는 새로운 이니셜라이져를 만들 수 있다.
class Poodle: Dog {
init(name: String) {
super.init(name: name, breed: “Poodle”)
}
}
보안상의 이유로, 스위프트는 자식 클래스에서는 항상 super.init()을 호출하도록 한다. – 자식 클래스가 생성될 때 부모 클래스가 중요한 작업을 할 경우를 대비하는 것이다.
자식 클래스들은 부모 클래스의 매서드를 자체 구현으로 대체할 수 있다. – overriding(재정의)라고 알려진 과정이다.
class Dog {
func makeNoise() {
print(“Woof!”)
}
}
class Poodle: Dog {
}
let puppy = Poodle()
puppy.makeNoise()
매서드 재정의로 Poodle 클래스의 makeNoise() 의 실행을 바꿀 수 있다.
class Poodle : Dog {
override func makeNoise() {
print(“Yip!”)
}
}
이 변화로 puppy.makeNoise() 는 “Woof!”가 아니라 “Yip!” 를 출력할 것이다.
클래스 상속이 매우 유용하더라도 – 실제로 Apple platform의 많은 부분에서 클래스를 사용하도록 요구한다
때로는 다른 개발자가 네가 만든 클래스를 기반으로 자신의 클래스를 빌드하는 것을 허용하고 싶지 않을 수도 있다.
Swift는 이를 위해 final 키워드를 제공한다
이는 네가 설정한 실행을 바꾸기 위해 너의 매서드를 재정의 할 수 없다는 뜻이다.
그들은 너의 클래스를 작성된 방식으로만 사용해야한다.
final class Dog {
var name : String
var breed: String
init(name: String, breed: String) {
self.name = name
self.breed = breed
}
}
세 번째 차이점은 복사되는 방식이다.
class Singer {
var name = “Taylor Swift”
}
var singer = Singer()
print(singer.name)
var singerCopy = Singer()
singerCopy.name = “Justin Bieber”
print(singer.name)
struct Singer {
var name = “Taylor Swift”
}
클래스와 구조체의 네 번째 차이점은 클래스는 Deinitializer를 가진다는 것이다 – 클래스의 인스턴스가 파괴되었을 때 실행되는 코드이다.
class Person {
var name : String
init() {
print(“\(name) is alive!”)
}
func printGreeting() {
print(“Hello, I’m \(name)!”)
}
}
for _ in 1…3 {
let person = Person()
person.printGreeting()
}
deinit {
print(“\(name) is no more!”)
}
클래스와 구조체 간의 마지막 차이점은 상수를 다루는 방식이다.
만약 변수 프로퍼티를 가지는 상수 구조체라면 구조체가 상수기 때문에 그 프로퍼티는 변경될 수 없다.
그러나, 만약 변수 프로퍼티를 가지는 상수 클래스라면, 그 프로퍼티는 변경될 수 있다.
이 때문에 클래스는 프로퍼티를 변경시키는 매서드에 사용하는 mutating 키워드가 필요 없다; 이것은 구조체에서만 필요로 한다.
class Singer {
var name: “Taylor Swift”
}
let taylor = Singer()
taylor.name = “Ed Sheeran”
print(taylor.name)
class Singer {
let name = “Taylor Swift”
}