从协议扩展中调用 class 属性

Calling class properties from within protocol extension

在为默认实现使用协议扩展时我遇到了问题。我定义了一个具有不同可选属性和功能的协议来使用。在扩展中,我实现了一个默认函数和 nil 属性。在实现中,我使用协议中的属性和函数。

在设备上它按我预期的方式工作。同样在调试器上,当我 运行 进入扩展实现中的断点时,它给了我来自 class 的 属性。

谁能帮我解决为什么我没有从 class 中得到示例中的 属性 而从扩展中得到 nil 属性 的原因。

操场上的例子

import UIKit

protocol Collectable {

    var item: String?  { get }
    func collect()
}

extension Collectable {
    var item: String?  { return nil }
    func collect() {
        if let some = item {
            print("collect \(some)")
        } else {
            print("nothing")
        }
    }
}

class Car: Collectable {
    var item = "letter"
}

let car = Car()
car.collect()

在协议中,您的项目是可选字符串,而在您的 class 中,您声明了另一个名为项目的变量。您的收集功能正在寻找可选项目,并且在扩展中您指定它应该 return nil.

正如@SavcaMarin 在他们的回答中所述,您在扩展程序 (String?) 中声明的 item 属性 与 [=13= 中声明的类型之间存在类型冲突] (String).

如果您评论扩展程序,您可以看到这个。编译器会告诉你Car不符合Collectable。如果您要求它创建所需的存根,它将创建 func collectvar item: String?。然后它给出一个错误 item 被重新定义。

正如 Rob 和 Matt 在对另一个答案的评论中指出的那样,这似乎是 Swift 编译器中的一个错误。如果有满足协议一致性的默认实现(您的扩展),它并不表示 item 的重新定义或您的 item 不符合协议。

简单的解决方法是通过显式声明类型(String?) 而不是依赖类型推断(给出 String):

class Car: Collectable {    
    var item:String? = "letter"
}