이번 편의 목표: 클래스 인스턴스를 두 변수가 공유하게 하고, 구조체의 복사와 다른 점을 출력으로 확인합니다.

클래스는 참조 타입입니다. 변수에 담기는 것은 인스턴스의 참조입니다. 다른 변수에 넣어도 같은 인스턴스를 가리킵니다. 멤버를 바꾸는 메서드에 mutating을 붙이지 않습니다.

Swift
class ReadingList {
    var titles: [String] = []

    func add(_ title: String) {
        titles.append(title)
    }
}

let original = ReadingList()
let shared = original
original.add("개미")
shared.add("공책")
print(original.titles)
print(shared.titles)

두 출력 모두 개미와 공책입니다. original과 shared가 같은 인스턴스이기 때문입니다. let이어도 add가 가능합니다. let이 고정하는 것은 참조이고, 인스턴스 안의 var는 메서드가 바꿀 수 있습니다.

상속이 필요하면 클래스를 씁니다. 부모의 메서드를 자식이 바꾸려면 override를 붙입니다.

Swift
class Fee {
    func cost(days: Int) -> Int {
        days * 100
    }
}

class VideoFee: Fee {
    override func cost(days: Int) -> Int {
        days * 300
    }
}

let fee: Fee = VideoFee()
print(fee.cost(days: 3))

fee의 타입은 Fee이지만 실제 인스턴스는 VideoFee이므로 900이 출력됩니다. 스위프트의 클래스 메서드는 기본적으로 재정의 대상입니다. 더 이상 재정의를 막으려면 final을 붙입니다.

같은 데이터를 복사해 서로 영향이 없어야 하면 06편의 구조체가 맞습니다. 목록 화면과 상세 화면이 같은 읽기 목록을 봐야 하면 클래스가 맞습니다.

직접 해 보기

shared에만 한 권을 더 추가한 뒤 original.titles의 원소 수가 3인지 확인하세요.

해설

shared.add는 original이 가리키는 같은 배열에 넣습니다. 구조체였다면 대입 시점의 복사본만 바뀌어 original의 수는 2로 남습니다.