当前位置: 首页 > 面试题库 >

具有超类和子类的Swift协议扩展方法分派

时经纬
2023-03-14
问题内容

我发现了一个有趣的行为,似乎是一个错误…

基于行为描述了以下文章:

https://medium.com/ios-os-x-development/swift-protocol-extension-method-
dispatch-6a6bf270ba94

http://nomothetis.svbtle.com/the-ghost-of-swift-bugs-
future

当添加时SomeSuperclass,输出不是我期望的,而不是直接采用协议。

protocol TheProtocol {
    func method1()
}

extension TheProtocol {
    func method1() {
        print("Called method1 from protocol extension")
    }
    func method2NotInProtocol() {
        print("Called method2NotInProtocol from protocol extension")
    }
}

// This is the difference - adding a superclass
class SomeSuperclass: TheProtocol {
}

// It works as expected when it simply adopts TheProtocol, but not when it inherits from a class that adopts the protocol
class MyClass: SomeSuperclass {
    func method1() {
        print("Called method1 from MyClass implementation")
    }
    func method2NotInProtocol() {
        print("Called method2NotInProtocol from MyClass implementation")
    }
}

let foo: TheProtocol = MyClass()
foo.method1()  // expect "Called method1 from MyClass implementation", got "Called method1 from protocol extension"
foo.method2NotInProtocol()  // Called method2NotInProtocol from protocol extension

您知道这是错误还是设计使然?一位同事建议混合继承和协议扩展可能无法按预期工作。我打算使用协议扩展来提供默认的实现…如果我做不到,那么我将不得不标记它@objc并返回到可选协议。


问题答案:

摘自The Swift Bugs Future的Ghost帖子,这是帖子末尾提到的协议扩展的分发规则。

  1. 如果变量的推断类型是协议:
  2. 并且该方法在原始协议中定义,然后调用运行时类型的实现,而不管扩展中是否存在默认实现。
  3. 并且该方法未在原始协议中定义,然后调用默认实现。
  4. 如果变量的推断类型是类型,则调用该类型的实现。

因此,根据您的情况,您是说method1()在协议中定义,并且已在子类中实现。但是您的超类正在采用协议,但未实现method1(),子类只是从超类继承而未直接采用协议。这就是为什么我认为这就是为什么当您调用foo.method1()时,它没有调用第1点和第2点所述的子类实现的原因。

但是当你这样做时

class SomeSuperclass: TheProtocol {
func method1(){
 print("super class implementation of method1()")}
}

class MyClass : SomeSuperclass {

override func method1() {
    print("Called method1 from MyClass implementation")
}

override func method2NotInProtocol() {
    print("Called method2NotInProtocol from MyClass implementation")
}
}

然后当你打电话时,

 let foo: TheProtocol = MyClass()
foo.method1()  // Called method1 from MyClass implementation
foo.method2NotInProtocol()

因此,此bug(似乎是bug)的解决方法是,您需要在超类中实现protocol方法,然后需要在子类中覆盖protocol方法。高温超导



 类似资料:
  • 问题内容: 我遇到了以下代码(Swift 3.1)中解释的问题: 因此,我希望在调用后应打印 _“ SubClassmethodA”_文本。但是由于某种原因,调用了from协议扩展的默认实现。但是,呼叫按预期方式工作。 是协议方法调度中的另一个Swift错误,还是我丢失了一些东西并且代码正常工作? 问题答案: 这就是协议当前调度方法的方式。 协议见证表(有关更多信息,请参见WWDC谈话)用于在协议

  • 问题内容: 我正在尝试使用Swift协议扩展,却发现这种行为令人困惑。您能帮我得到我想要的结果吗? 请参阅代码最后4行的注释。(如果需要,可以将其复制粘贴到Xcode7游乐场)。谢谢!! 问题答案: 简短的答案是协议扩展不执行类多态性。这是有一定道理的,因为协议可以被结构或枚举采用,并且因为我们不希望仅在没有必要的地方采用协议来引入动态调度。 因此,在中,实例变量(可能更准确地写为)并不意味着您认

  • 协议和扩展 你可以扩展一个已经存在的类型来采纳和遵循一个新协议, 就算是你无法访问现有类型的源代码也行. 扩展可以添加新的属性、方法和下标到已经存在的类型, 并且因此允许你添加协议需要的任何需要. protocol TextRepresentable { var textualDescription: String { get } } // 此处并无Dice这个类, 以及其sides属性

  • 问题内容: 通过在Swift 2.0中添加协议扩展,似乎协议基本上已经成为Java / C#抽象类。我可以看到的唯一区别是抽象类仅限于单个继承,而Swift类型可以符合任何数量的协议。 这是对Swift 2.0中协议的正确理解,还是有其他区别? 问题答案: 有几个重要的区别… 协议扩展可以与值类型以及类一起使用。 值类型是结构和枚举。例如,你可以扩展到增加财产所有整数类型(,,等)。或者,您可以将

  • 问题内容: 由于Xcode 6在Swift中仍然存在很多错误,因此我不确定是其中之一还是缺少某些东西。我的班采用协议NSLayoutManagerDelegate。但是似乎无法覆盖我需要的方法。我做的文档描述如下: 但是我在这里遇到错误:方法不会覆盖其超类中的任何方法。我该怎么办? 问题答案: 是的,您正在从协议中实现方法,但这不是替代。只需删除关键字。覆盖是指您的超类也实现该方法,并且您要提供一

  • 问题内容: 给定两个协议及其扩展名: 并尝试使它们都符合: 我收到编译时错误: 类型“ SomeClass”不符合协议“ FirstDelegate” 交换和: 产生反向: 类型“ SomeClass”不符合协议“ SecondDelegate” 删除扩展之一可以解决此问题。同上为内部提供实现。 这个协议扩展功能对我来说还很新。此外,目前苹果官方的“快速编程指南(预发行版)”中有关此信息的信息很少