문제는 컴파일러가 당신이 지킬 것이라는 것을 증명할 수 없다는 약속을하고 있다는 것입니다.
그래서이 약속을 만들었습니다 : 호출 copy()
은 완전히 초기화 된 자체 유형을 반환합니다.
그러나 다음과 같이 구현 copy()
했습니다.
func copy() -> Self {
return C()
}
이제 나는 재정의하지 않는 하위 클래스입니다 copy()
. 그리고 나는 C
완전히 초기화되지 않은 Self
(내가 약속 한)를 반환합니다 . 그래서 그것은 좋지 않습니다. 어때 :
func copy() -> Self {
return Self()
}
음, 그것은 컴파일되지 않을 것입니다.하지만 그렇게되었다고해도 좋지 않을 것입니다. 하위 클래스에는 사소한 생성자 D()
가 없을 수 있으므로 합법적이지 않을 수도 있습니다. (아래를 참조하십시오.)
좋습니다. 다음은 어떻습니까?
func copy() -> C {
return C()
}
예,하지만 반환되지 않습니다 Self
. 반환합니다 C
. 당신은 여전히 당신의 약속을 지키지 않고 있습니다.
"하지만 ObjC는 할 수 있습니다!" 글쎄요. 대부분은 Swift가하는 것처럼 약속을 지키더라도 상관하지 않기 때문입니다. copyWithZone:
하위 클래스에서 구현 하지 못하면 객체를 완전히 초기화하지 못할 수 있습니다. 컴파일러는 당신이 그렇게했다는 경고조차하지 않을 것입니다.
"그러나 ObjC의 대부분은 Swift로 번역 될 수 있으며 ObjC는 NSCopying
." 예, 그렇습니다. 정의 된 방법은 다음과 같습니다.
func copy() -> AnyObject!
따라서 동일한 작업을 수행 할 수 있습니다 (여기에는!에 대한 이유가 없습니다).
protocol Copyable {
func copy() -> AnyObject
}
그것은 "나는 당신이 돌려받는 것에 대해 아무것도 약속하지 않습니다."라고 말합니다. 다음과 같이 말할 수도 있습니다.
protocol Copyable {
func copy() -> Copyable
}
그것은 당신이 할 수있는 약속입니다.
하지만 잠시 동안 C ++에 대해 생각하고 수 있습니다 . 우리와 우리의 모든 서브 클래스가 특정 종류의 이니셜 라이저를 구현할 것이라고 약속 할 수 있으며, Swift는이를 강제 할 것입니다 (따라서 우리가 진실을 말하고 있음을 증명할 수 있습니다).
protocol Copyable {
init(copy: Self)
}
class C : Copyable {
required init(copy: C) {
}
}
이것이 복사를 수행하는 방법입니다.
한 단계 더 dynamicType
나아갈 수는 있지만를 사용하며 항상 우리가 원하는 것인지 확인하기 위해 광범위하게 테스트하지는 않았지만 정확해야합니다.
protocol Copyable {
func copy() -> Self
init(copy: Self)
}
class C : Copyable {
func copy() -> Self {
return self.dynamicType(copy: self)
}
required init(copy: C) {
}
}
여기서 우리는 우리를 위해 복사를 수행하는 이니셜 라이저가 있다는 것을 약속하고, 런타임에 호출 할 것을 결정할 수 있으며, 찾고 있던 메소드 구문을 제공합니다.