覆盖实例var的默认值

Pat*_*ini 11 overriding instance-variables default-value subclassing swift

鉴于上课Obj,

class Obj: NSObject {
    var x = "x"
}
Run Code Online (Sandbox Code Playgroud)

和它的子类,Obj1你如何更改默认值var x

简单地设置一个新值将是最有意义的,但似乎错误...

class Obj1: Obj {
    var x = "y"
}
Run Code Online (Sandbox Code Playgroud)

❗️无法覆盖存储的属性'x'

Eri*_*rik 9

在大多数情况下,通过注入这些值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)
    }
}
Run Code Online (Sandbox Code Playgroud)

但是,在某些情况下,您希望覆盖计算属性或可能未完全初始化的内容.

在这种情况下,您可以使用以下override var语法:

override var x : String
{
    get { return super.x }      // get super.x value
    set { super.x = newValue }  // set super.x value
}
Run Code Online (Sandbox Code Playgroud)

上面的代码不会改变行为,但会说明允许您这样做的语法.


Chr*_*ver 6

这个问题已被标记为已回答,但是通过委派给计算属性,还有一个安全的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
Run Code Online (Sandbox Code Playgroud)

更安全的是,我指的是Swift执行的初始化序列,它可以防止"虚拟"调用问题进入一个尚未构建的子类(即,基类调用一个在子类中实现的虚方法,但之前该子类已完成初始化).例如,这在C++中是一种危险.


GoZ*_*ner 3

init()方法定义为:

init () {
  super.init()
  x = "y"
}
Run Code Online (Sandbox Code Playgroud)

您将希望任何其他初始值设定项Obj1将其调用为self.init()。Apple 文档对指定初始值设定项和相对初始值设定项的继承进行了长时间的讨论。