为什么传递给函数的协议默认值没有改变,即使函数在子类化时改变了?
Why does the protocol default value passed to the function not change, even though the function does when subclassing?
我有一个协议,我已经为其分配了一些默认值:
protocol HigherProtocol {
var level: Int { get }
func doSomething()
}
extension HigherProtocol {
var level: Int { 10 }
func doSomething() {
print("Higher level is \(level)")
}
}
然后我有另一个协议,它符合更高级别的协议,但具有不同的默认值和功能实现:
protocol LowerProtocol: HigherProtocol {}
extension LowerProtocol {
var level: Int { 1 }
func doSomething() {
print("Lower level is \(level)")
}
}
然后我创建一个符合HigherProtocol的class,然后创建一个符合lower level协议的subclass:
class HigherClass: HigherProtocol {}
class LowerClass: HigherClass, LowerProtocol {}
然而,当我实例化这个较低的 class 时,它显示了一些奇怪的行为:
let lowerClass = LowerClass()
lowerClass.level // is 1
lowerClass.doSomething() // Prints "Lower level is 10" to the console.
默认的 属性 是正确的,但函数的默认实现似乎是两者的混合体。
我想知道这里发生了什么?
协议是存在类型,这就是您感到困惑的原因。您需要向 class 类型的协议类型公开。在你的情况下,你可以做 LowerProtocol
或 HigherProtocol
所以它现在打印 10 。让我们像这样
let lowerClass: LowerProtocol = LowerClass()
或
let lowerClass: HigherProtocol = LowerClass()
lowerClass.level // now prints 10
lowerClass.doSomething() // Prints "Lower level is 10" to the console.
您似乎在尝试使用协议来创建多重继承。它们不是为此而设计的,即使你让它工作,你也会被咬几次。协议不能替代继承,无论是多重继承还是其他方式。 (通常,Swift 支持组合而不是任何形式的继承。)
这里的问题是 HigherClass 符合 HigherProtocol,因此现在有 level
和 doSomething
的实现。 LowerClass 继承自它,并希望覆盖这些实现。但是覆盖在协议扩展中,这是未定义的行为。请参阅 Swift 编程语言中的 Extensions:
Extensions can add new functionality to a type, but they cannot override existing functionality.
未定义的行为并不意味着“它不会覆盖”。这意味着“任何事情都可能发生”,包括这种有时被覆盖有时不被覆盖的奇怪情况。
(作为旁注,Objective-C 中的情况类似。在两个不同的类别中实现一个方法会导致不确定调用哪个类别,并且在发生这种情况时不会出现警告或错误提示。 Swift 的优化可以使行为更加令人惊讶。)
我希望编译器能够检测到这些类型的错误并引发错误,但它没有。您需要重新设计系统才能不这样做。
我有一个协议,我已经为其分配了一些默认值:
protocol HigherProtocol {
var level: Int { get }
func doSomething()
}
extension HigherProtocol {
var level: Int { 10 }
func doSomething() {
print("Higher level is \(level)")
}
}
然后我有另一个协议,它符合更高级别的协议,但具有不同的默认值和功能实现:
protocol LowerProtocol: HigherProtocol {}
extension LowerProtocol {
var level: Int { 1 }
func doSomething() {
print("Lower level is \(level)")
}
}
然后我创建一个符合HigherProtocol的class,然后创建一个符合lower level协议的subclass:
class HigherClass: HigherProtocol {}
class LowerClass: HigherClass, LowerProtocol {}
然而,当我实例化这个较低的 class 时,它显示了一些奇怪的行为:
let lowerClass = LowerClass()
lowerClass.level // is 1
lowerClass.doSomething() // Prints "Lower level is 10" to the console.
默认的 属性 是正确的,但函数的默认实现似乎是两者的混合体。
我想知道这里发生了什么?
协议是存在类型,这就是您感到困惑的原因。您需要向 class 类型的协议类型公开。在你的情况下,你可以做 LowerProtocol
或 HigherProtocol
所以它现在打印 10 。让我们像这样
let lowerClass: LowerProtocol = LowerClass()
或
let lowerClass: HigherProtocol = LowerClass()
lowerClass.level // now prints 10
lowerClass.doSomething() // Prints "Lower level is 10" to the console.
您似乎在尝试使用协议来创建多重继承。它们不是为此而设计的,即使你让它工作,你也会被咬几次。协议不能替代继承,无论是多重继承还是其他方式。 (通常,Swift 支持组合而不是任何形式的继承。)
这里的问题是 HigherClass 符合 HigherProtocol,因此现在有 level
和 doSomething
的实现。 LowerClass 继承自它,并希望覆盖这些实现。但是覆盖在协议扩展中,这是未定义的行为。请参阅 Swift 编程语言中的 Extensions:
Extensions can add new functionality to a type, but they cannot override existing functionality.
未定义的行为并不意味着“它不会覆盖”。这意味着“任何事情都可能发生”,包括这种有时被覆盖有时不被覆盖的奇怪情况。
(作为旁注,Objective-C 中的情况类似。在两个不同的类别中实现一个方法会导致不确定调用哪个类别,并且在发生这种情况时不会出现警告或错误提示。 Swift 的优化可以使行为更加令人惊讶。)
我希望编译器能够检测到这些类型的错误并引发错误,但它没有。您需要重新设计系统才能不这样做。