[inheritance] Swift에서 저장된 속성 재정의

컴파일러가 저장된 속성을 다른 저장된 값으로 재정의하는 것을 허용하지 않는다는 것을 알았습니다 (이상하게 보입니다).

class Jedi {
    var lightSaberColor = "Blue"
}


class Sith: Jedi {
    override var lightSaberColor = "Red" // Cannot override with a stored property lightSaberColor
}

그러나 계산 된 속성으로이 작업을 수행 할 수 있습니다.

class Jedi {
    let lightSaberColor = "Blue"
}


class Sith: Jedi {
    override var lightSaberColor : String{return "Red"}

}

다른 가치를 부여 할 수없는 이유는 무엇입니까?

저장된 속성으로 재정의하는 것이 혐오스러운 일이고 계산 된 코셔로하는 이유는 무엇입니까? 그들은 무엇을 생각합니까?



답변

다른 가치를 부여 할 수없는 이유는 무엇입니까?

상속 된 속성에 다른 값을 부여 할 수 있습니다. 해당 초기 값을 사용하는 생성자에서 속성을 초기화하고 파생 클래스에서 다른 값을 전달하면이 작업을 수행 할 수 있습니다.

class Jedi {
    // I made lightSaberColor read-only; you can make it writable if you prefer.
    let lightSaberColor : String
    init(_ lsc : String = "Blue") {
        lightSaberColor = lsc;
    }
}

class Sith : Jedi {
    init() {
        super.init("Red")
    }
}

let j1 = Jedi()
let j2 = Sith()

println(j1.lightSaberColor)
println(j2.lightSaberColor)

속성을 재정의하는 것은 새 값을 제공하는 것과는 다릅니다. 클래스에 다른 속성을 제공하는 것과 비슷합니다. 실제로는 계산 된 속성을 재정의 할 때 발생합니다. 기본 클래스의 속성 을 계산하는 코드는 파생 클래스의 해당 속성에 대한 재정의를 계산하는 코드 로 대체 됩니다.

실제 저장된 속성을 재정의 할 수 lightSaberColor있습니까? 즉, 다른 동작이 있습니까?

관찰자 외에 저장된 속성에는 동작이 없으므로 실제로 재정의 할 것이 없습니다. 위에 설명 된 메커니즘을 통해 속성에 다른 값을 부여 할 수 있습니다. 이것은 다른 구문으로 질문의 예가 ​​달성하려는 것을 정확히 수행합니다.


답변

나를 위해 귀하의 예제는 Swift 3.0.1에서 작동하지 않습니다.

놀이터에이 코드를 입력했습니다.

class Jedi {
    let lightsaberColor = "Blue"
}

class Sith: Jedi {
    override var lightsaberColor : String {
        return "Red"
    }
}

Xcode에서 컴파일 타임에 오류가 발생합니다.

변경 불가능한 ‘let’속성 ‘lightsaberColor’를 ‘var’의 getter로 재정의 할 수 없습니다.

아니요, 저장된 속성의 유형을 변경할 수 없습니다. Liskov Substitution Principle 수퍼 클래스가 필요한 곳에서 서브 클래스가 사용되도록 강제 합니다.

그러나이를로 변경 하여 계산 된 속성에 var추가하는 set경우 동일한 유형의 계산 된 속성으로 저장된 속성을 재정의 할 수 있습니다.

class Jedi {
    var lightsaberColor = "Blue"
}


class Sith: Jedi {
    override var lightsaberColor : String {
        get {
            return "Red"
        }
        set {
            // nothing, because only red is allowed
        }
    }
}

이것은 저장된 속성에서 계산 된 속성으로 전환하는 것이 합리적 일 수 있기 때문에 가능합니다.

그러나 저장된 var속성을 저장된 속성으로 재정의하는 var것은 의미가 없습니다. 속성 값만 변경할 수 있기 때문입니다.

그러나 저장된 속성을 저장된 속성으로 재정의 할 수는 없습니다.


나는 Sith가 Jedi라고 말하지 않을 것이다 :-P. 따라서 이것이 작동하지 않는다는 것이 분명합니다.


답변

class SomeClass {
    var hello = "hello"
}
class ChildClass: SomeClass {
    override var hello: String {
        set {
            super.hello = newValue
        }
        get {
            return super.hello
        }    
    }
}


답변

속성에 다른 값을 지정하고 싶을 것입니다.

class Jedi {
    var lightSaberColor = "Blue"
}


class Sith: Jedi {
    override init() {
        super.init()
        self.lightSaberColor = "Red"
    }
}


답변

Swift 4의 경우 Apple 문서에서 :

상속 된 인스턴스 또는 유형 속성을 재정 의하여 해당 속성에 대한 고유 한 사용자 정의 getter 및 setter를 제공하거나 재정의 속성이 기본 속성 값이 변경 될 때 관찰 할 수 있도록 속성 관찰자를 추가 할 수 있습니다.


답변

Swift에서는 안타깝게도 불가능합니다. 가장 좋은 대안은 다음과 같습니다.

class Jedi {
    private(set) var lightsaberColor = "Blue"
}


class Sith: Jedi {
    override var lightsaberColor : String {
        get {
            return "Red"
        }
    }
}


답변

뷰 컨트롤러에 상수를 설정하는 데 동일한 문제가 발생했습니다.

인터페이스 빌더를 사용하여 뷰를 관리하기 init()때문에를 사용할 수 없으므로 해결 방법은 기본 및 상속 된 클래스 모두에서 읽기 전용 계산 변수를 사용한 것을 제외하고는 다른 답변과 유사했습니다.

class Jedi {
    var type: String {
        get { return "Blue" }
    }
}

class Sith: Jedi {
    override var type: String {
        get { return "Red" }
    }
}