简体   繁体   English

为什么传递给 function 的协议默认值不会改变,即使子类化时 function 会改变?

[英]Why does the protocol default value passed to the function not change, even though the function does when subclassing?

I have a protocol, to which I have assigned some default values:我有一个协议,我为其分配了一些默认值:

protocol HigherProtocol {
    var level: Int { get }
    
    func doSomething()
}

extension HigherProtocol {
    var level: Int { 10 }
    
    func doSomething() {
        print("Higher level is \(level)")
    }
}

Then I have another protocol which conforms to the higher level protocol, but has different default values and implementation of functions:然后我有另一个符合更高级别协议的协议,但具有不同的默认值和功能实现:

protocol LowerProtocol: HigherProtocol {}

extension LowerProtocol {
    var level: Int { 1 }
    
    func doSomething() {
        print("Lower level is \(level)")
    }
}

I then create a class that conforms to the HigherProtocol, and then a subclass that conforms to the lower level protocol:然后我创建一个符合上层协议的 class,然后创建一个符合下层协议的子类:

class HigherClass: HigherProtocol {}

class LowerClass: HigherClass, LowerProtocol {}

When I instantiate this lower class, however, it displays some odd behaviour:但是,当我实例化这个较低的 class 时,它会显示一些奇怪的行为:

let lowerClass = LowerClass()

lowerClass.level // is 1

lowerClass.doSomething() // Prints "Lower level is 10" to the console.

The default property is correct, but the default implementation of the function seems to be a hybrid of the two.默认属性是正确的,但是 function 的默认实现似乎是两者的混合。

I'm wondering what's happening here?我想知道这里发生了什么?

You appear to be trying to use protocols to create multiple-inheritance.您似乎正在尝试使用协议来创建多重继承。 They're not designed for that, and even if you get this working, you're going to get bitten several times.它们不是为此而设计的,即使你得到这个工作,你也会被咬几次。 Protocols are not a replacement for inheritance, multiple or otherwise.协议不能替代 inheritance,多个或其他。 (As a rule, Swift favors composition rather than inheritance in any form.) (作为一项规则,Swift 倾向于组合而不是任何形式的 inheritance。)

The problem here is that HigherClass conforms to HigherProtocol and so now has implementations for level and doSomething .这里的问题是 HigherClass 符合 HigherProtocol ,因此现在有leveldoSomething的实现。 LowerClass inherits from that, and wants to override those implementations. LowerClass 继承自它,并希望覆盖这些实现。 But the overrides are in a protocol extension, which is undefined behavior.但是覆盖在协议扩展中,这是未定义的行为。 SeeExtensions from The Swift Programming Language:请参阅 Swift 编程语言的扩展

Extensions can add new functionality to a type, but they cannot override existing functionality.扩展可以为类型添加新功能,但不能覆盖现有功能。

Undefined behavior doesn't mean "it doesn't override."未定义的行为并不意味着“它不会覆盖”。 It means "anything could happen" including this weird case where it sometimes is overridden and sometimes isn't.这意味着“任何事情都可能发生”,包括这种奇怪的情况,有时会被覆盖,有时不会。

(As a side note, the situation is similar in Objective-C. Implementing a method in two different categories makes it undefined which one is called, and there's no warning or error to let you when this happens. Swift's optimizations can make the behavior even more surprising.) (作为旁注,Objective-C 中的情况类似。在两个不同类别中实现一个方法会导致不确定调用哪个类别,并且在发生这种情况时没有警告或错误让您。Swift 的优化可以使行为更加令人惊讶.)

I wish the compiler could detect these kinds of mistakes and raise an error, but it doesn't.我希望编译器能够检测到这些类型的错误并引发错误,但事实并非如此。 You'll need to redesign your system to not do this.你需要重新设计你的系统来避免这样做。

Protocols are existential types that is why you are confused.协议是存在类型,这就是您感到困惑的原因。 You need to expose to protocol types of your class Type.您需要公开 class 类型的协议类型。 In your case you can do LowerProtocol or HigherProtocol so it prints 10 now.在您的情况下,您可以执行LowerProtocolHigherProtocol ,以便现在打印 10。 Let`s make like this让我们像这样

let lowerClass: LowerProtocol = LowerClass()

or或者

let lowerClass: HigherProtocol = LowerClass()

lowerClass.level // now prints 10

lowerClass.doSomething() // Prints "Lower level is 10" to the console.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 为什么以下协议具有此必需功能? - Why does the following protocol have this required function? 什么时候调用协议功能? - When does a protocol function get called? 协议数组元素是按值传递还是按引用传递? - Does protocol array elements passed by value or reference? 为什么即使传递了一个值,中继的订阅也不起作用? - Why doesn't the subscription of the relay work even though there is a value passed to it? 协议功能将值发送回第一个VC,但未将其设置为变量 - Protocol function sends the value back to the first VC but does not set it to the variables 为什么编译器看不到协议中的默认代码? - Why does the compiler not see the default code in a protocol? Swift / iOS控制器传递给函数时不保留委托 - Swift/iOS Controller Does not Retain Delegate when Passed to a Function 即使在创建函数后,Swift中的UIButton图像也不会更改颜色 - UIButton image in Swift does not change colors even after a function is created 为什么我的 Xcode 编译器告诉我我使用的是值类型,即使我使用的是类? - Why does my Xcode compiler tell me I use a value type even though I use classes? UITableViewController中的行号不符合协议功能 - Row number in UITableViewController does not conform the protocol function
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM