覆盖实例var的默认值

时间:2014-06-09 14:53:39

标签: override swift default-value instance-variables subclassing

鉴于课程Obj

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

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

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

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

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

4 个答案:

答案 0 :(得分: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)
    }
}

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

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

override var x : String
{
    get { return super.x }      // get super.x value
    set { super.x = newValue }  // set super.x value
}

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

答案 1 :(得分:6)

这个问题已被标记为已回答,但还有一个安全的Swift template method pattern通过委派给计算属性:

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 ++中是一种危险。

答案 2 :(得分:3)

init()方法定义为:

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

您希望Obj1中的任何其他初始值设定项都以self.init()的形式调用它。 Apple文档对指定的初始化程序以及与初始化程序的继承进行了长时间的讨论。

答案 3 :(得分:1)

在swift 3中,我发现chrisco的解决方案不再适用了, 但是,如果使用Child在基类中声明变量,它就可以工作。

private(set)