developer tip

Swift에서 저장된 속성 재정의

copycodes 2020. 8. 13. 23:32
반응형

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"
    }
}

Throws error at compile time in Xcode:

cannot override immutable 'let' property 'lightsaberColor' with the getter of a 'var'

No you can not change the type of a stored property. The Liskov Substitution Principle forces you to allow that a subclass be used in a place where the superclass is wanted.

But if you change it to var and therefore add the set in the computed property you can override the stored property with a computed property of the same type.

class Jedi {
    var lightsaberColor = "Blue"
}


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

This is possible because it can make sense to switch from stored property to computed property.

But override a stored var property with a stored var property does not make sense, because you can ony change the value of the property.

You can however not override a stored property with a stored property at all.


I would not say Sith are Jedi :-P. Therefore it is clear that this can not work.


You probably want to assing another value to the property:

class Jedi {
    var lightSaberColor = "Blue"
}


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

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

For Swift 4, from Apple's documentation:

You can override an inherited instance or type property to provide your own custom getter and setter for that property, or to add property observers to enable the overriding property to observe when the underlying property value changes.


In Swift, this is unfortunately not possible to do. The best alternative is the following:

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


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

I had the same problem to set a constant for a view controller.

As I'm using interface builder to manage the view, I cannot use init(), so my workaround was similar to other answers, except I used a read-only computed variable on both base and inherited classes.

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

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

You also can use a function to override. It's not direct answer, but can enrich this topic)

Class A

override func viewDidLoad() {
    super.viewDidLoad()

    if shouldDoSmth() {
       // do
    }
}

public func shouldDoSmth() -> Bool {
    return true
}

Class B: A

public func shouldDoSmth() -> Bool {
    return false
}

참고URL : https://stackoverflow.com/questions/26691935/overriding-a-stored-property-in-swift

반응형