覆盖 Swift 中的 getter

Overriding getter in Swift

我有一种情况需要覆盖 属性 的 getter。

假设我们有:

public class MyBaseClass {
    private var _name: String
    public internal(set) var name: String {
        get {
            return self._name
        }
        set {
            self._name = newValue
        }
    }
}

我想没什么特别的。

现在,如果我尝试覆盖派生的 class 中的 getter:

public class MyDerivedClass: MyBaseClass {
    public var name: String {
        get {
            return "Derived - \(super.name)"
        }
    }
}

我收到编译错误:无法用只读覆盖可变 属性 属性 'name'.

如果我尝试添加 setter 并覆盖它:

public class MyDerivedClass: MyBaseClass {
    public internal(set) var name: String {
        get {
            return "Derived - \(super.name)"
        }
        set {
            super.name = newValue
        }
    }
}

我收到错误消息:Setter 覆盖 var 必须与其覆盖的声明一样可访问

如果我尝试以下操作:

public class MyDerivedClass: MyBaseClass {
    public internal(set) var name: String {
        get {
            return "Derived - \(super.name)"
        }
    }
}

然后,编译器崩溃了...

我怎样才能实现只覆盖 getter?

这对我有用:

public class MyBaseClass {
    private var _name: String = "Hi"
    public internal(set) var name: String {
        get {
            return self._name
        }
        set {
            self._name = newValue
        }
    }
}

public class MyDerivedClass:MyBaseClass {
    override public var name: String {
        get {
            return "Derived - \(super.name)"
        }
        set {
            super._name = newValue
        }
    }
}

MyDerivedClass().name

编辑

这段代码在 playground 中对我有用,将它放在 Sources -> SupportCode.swift 文件中

public class MyBaseClass {
private var _name: String = "Hi"
public internal(set) var name: String {
    get {
        return self._name
    }
    set {
        self._name = newValue
    }
}
public init() {

}

}

public class MyDerivedClass:MyBaseClass {
    override public var name: String {
        get {
            return "Derived - \(super.name)"
        }
        set {
           // do nothing
        }
    }
   public override init() {

    }
}

这有点令人困惑,因为我得到了与您相同的警告,即 internal(set) 不能放在被覆盖的 subclass 变量之前。这很可能是一个错误。而且我也在作弊以确保派生 class 的 setter 什么都不做。

internal(set)private(set)更常见的用法是有这样的代码,与文档中的代码类似:

public class MyBaseClass {
    public private(set) var _name: String = "Hi"
    public var name: String {
        get {
            return self._name
        }
        set {
            self._name = newValue
        }
    }
    public init() {

    }

}

public class MyDerivedClass:MyBaseClass {
    override public var name: String {
        get {
            return "Derived - \(super.name)"
        }
        set {
           super._name = newValue
        }
    }
   public override init() {

    }
}

这里的setter可以直接用MyDerivedClass()._name读取,但是不能修改,例如MyDerivedClass()._name = "Fred" 会引发错误,但 MyDerivedClass().name = "Fred" 没问题。

问题 1

MyBaseClass 不编译 因为:

  1. 它已存储 属性 (_name)
  2. 这个存储的 属性 是非可选的,所以它不能为 nil
  3. 没有初始化程序来填充它

所以首先我们需要为 MyBaseClass 添加一个合适的初始化器

public class MyBaseClass {
    private var _name: String
    public internal(set) var name: String {
        get { return self._name }
        set { self._name = newValue }
    }
    init(name : String){
        _name = name
    }
}

问题 2

现在我们可以声明 MyDerivedClass 来覆盖计算的 属性:

  1. 我们需要使用魔法关键字override
  2. 我们需要同时提供 setter 和 getter

代码如下:

public class MyDerivedClass: MyBaseClass {
    public override var name: String {
        get { return "Derived - \(super.name)" }
        set { super.name = newValue }
    }
}

测试

来自我的游乐场:

let somethingWithAName = MyDerivedClass(name: "default name")
println(somethingWithAName.name) // > "Derived - default name"
somethingWithAName.name = "another name"
println(somethingWithAName.name) // > "Derived - another name"