cfi*_*her 110 inheritance overriding properties 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"}
}
为什么我不允许给它另一个值?
为什么用存储的属性覆盖令人憎恶的东西并用计算的一个犹太教来做?他们在想什么?
das*_*ght 65
为什么我不允许给它另一个价值呢?
绝对允许您为继承的属性赋予不同的值.如果在获取该初始值的构造函数中初始化该属性,并从派生类传递不同的值,则可以执行此操作:
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具有其他一些行为?
除了观察者之外,存储的属性没有行为,所以没有任何东西可以覆盖.通过上述机制可以赋予财产不同的价值.这正是问题中的示例试图用不同的语法实现的.
Bin*_*ian 48
对我来说,你的例子在Swift 3.0.1中不起作用.
进入游乐场这段代码:
class Jedi {
    let lightsaberColor = "Blue"
}
class Sith: Jedi {
    override var lightsaberColor : String {
        return "Red"
    }
}
在Xcode中编译时引发错误:
无法使用'var'的getter覆盖不可变'let'属性'lightsaberColor'
不,您无法更改存储属性的类型.Liskov替换原则强制您允许在需要超类的地方使用子类.
但是,如果将其更改为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属性没有意义,因为您可以更改属性的值.
但是,您可以根本不使用存储属性覆盖存储的属性.
我不会说西斯是绝地:-P.因此很明显,这不起作用.
zis*_*oft 14
您可能想要为该属性分配另一个值:
class Jedi {
    var lightSaberColor = "Blue"
}
class Sith: Jedi {
    override init() {
        super.init()
        self.lightSaberColor = "Red"
    }
}
小智 14
class SomeClass {
    var hello = "hello"
}
class ChildClass: SomeClass {
    override var hello: String {
        set {
            super.hello = newValue
        }
        get {
            return super.hello
        }    
    }
}
如果您尝试在 Swift 5 中这样做,您将收到一个
无法使用“var”的 getter 覆盖不可变的“let”属性“lightSaberColor”
最好的办法是将其声明为计算属性。
这有效,因为我们只是覆盖了get {}函数
class Base {
   var lightSaberColor: String { "base" }
}
class Red: Base {
   override var lightSaberColor: String { "red" }
}
不幸的是,在Swift中,这是不可能的。最好的替代方法如下:
class Jedi {
    private(set) var lightsaberColor = "Blue"
}
class Sith: Jedi {
    override var lightsaberColor : String {
        get {
            return "Red"
        }
    }
}
Swift does not allow you to override a variable stored property Instead of this you can use computed property
class A {
    var property1 = "A: Stored Property 1"
    var property2: String {
        get {
            return "A: Computed Property 2"
        }
    }
    let property3 = "A: Constant Stored Property 3"
    //let can not be a computed property
    
    func foo() -> String {
        return "A: foo()"
    }
}
class B: A {
    //now it is a computed property
    override var property1: String {
        set { }
        get {
            return "B: overrode Stored Property 1"
        }
    }
    override var property2: String {
        get {
            return "B: overrode Computed Property 2"
        }
    }
    
    override func foo() -> String {
        return "B: foo()"
    }
    //let can not be overrode
}
func testPoly() {
    let a = A()
    
    XCTAssertEqual("A: Stored Property 1", a.property1)
    XCTAssertEqual("A: Computed Property 2", a.property2)
    
    XCTAssertEqual("A: foo()", a.foo())
    
    let b = B()
    XCTAssertEqual("B: overrode Stored Property 1", b.property1)
    XCTAssertEqual("B: overrode Computed Property 2", b.property2)
    
    XCTAssertEqual("B: foo()", b.foo())
    
    //B cast to A
    XCTAssertEqual("B: overrode Stored Property 1", (b as! A).property1)
    XCTAssertEqual("B: overrode Computed Property 2", (b as! A).property2)
    
    XCTAssertEqual("B: foo()", (b as! A).foo())
}
It is more clear when compare with Java, where a class field can not be overrode and does not support polymorphism because is defined in compile time(run efficiently). It is called a variable hiding[About] It is not recommended to use this technics because it is hard to read/support