覆盖实例var的默认值



给定类别Obj

class Obj: NSObject {
    var x = "x"
}

及其子类Obj1,如何更改var x的默认值?

简单地设置一个新值是最有意义的,但是似乎出错了…

class Obj1: Obj {
    var x = "y"
}

❗️无法使用存储属性'x'重写

在大多数情况下,通过init注入这些值是首选的方法。

例如:

class Foo
{
    var x : String
    convenience init()
    {
        self.init(x: "x")  // 'x' by default
    }
    init(x: String)
    {
        self.x = x
    }
}
class Bar : Foo
{
    convenience init()
    {
        self.init(x: "y")   // now 'y' by default
    }
    init(x: String)
    {
        super.init(x: x)
    }
}

但是,在某些情况下,您想要覆盖计算属性或可能没有完全初始化的内容。

在这种情况下,您可以使用override var语法:
override var x : String
{
    get { return super.x }      // get super.x value
    set { super.x = newValue }  // set super.x value
}

上面的代码不会改变行为,但是演示了允许您这样做的语法。

这个问题已经被标记为答案了,但是还有一种swift模板中安全的方法模式,通过委托给计算属性:

class Foo {
    lazy var x : String = self.defaultX
    var defaultX:String { return "foo" }
}
class Bar : Foo {
    override var defaultX:String { return "bar" }
}

println(Foo().x) // foo
println(Bar().x) // bar

更安全,我指的是Swift对初始化顺序的强制执行,以防止"虚拟"调用到尚未构造的子类(即,让基类调用在子类中实现的虚拟方法,但在子类完成初始化之前)的问题。例如,这在c++中就很危险。

定义init()方法为:

init () {
  super.init()
  x = "y"
}

您将希望Obj1中的任何其他初始化器都像self.init()一样调用它。Apple文档对指定初始化器和相对于初始化器的继承有很长的讨论。

在swift 3中,我发现chrisco的解决方案不再工作了,但是,如果您在基类中使用private(set)声明变量,则可以正常工作。

class Parent {
    private(set) var name = "Dad"
}
class Child: Parent {
    override var name: String { return "Son" }
}

最新更新