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

高健

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

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

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. AND方法在原始协议中定义,然后调用运行时类型的实现,而不管扩展中是否存在默认实现。
  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() 

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

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

具有子类数据的超类方法

Swift-具有通用超类约束的扩展中的协议默认实现

Swift 2.0中的协议扩展方法分派

为什么动态方法分派和超类变量可以引用子类对象?

超类和子类各自具有自己的接口

子类和超类方法

在Dart中,子类如何扩展具有父类的泛型的超类?

是否有来自具有子类方法仅调用覆盖的超类方法有什么好处?

斯威夫特:如何让具有子类返回类型的函数符合将超类定义为返回类型的协议?

超类和子类——方法使用

子类和超类

调用Swift协议扩展方法代替在子类中实现的方法

如果我使用超类来初始化子类对象,为什么该对象具有子类的属性,但是具有超类的方法呢?

Swift协议扩展,具有符合协议的属性

以子类为参数的重载方法,但具有称为超类的方法

如何让子类扩展python中超类的方法

在调用方法时获取扩展超类的子类实例

有没有更简单的方法可以在Java中的子类和超类的ArrayList上调用子类的方法

子类可以与超类具有相同的列名吗?

Swift 2.0协议扩展和Java / C#抽象类之间有区别吗?

创建持有超类和子类对象的对象数组的正确方法

超类和子类的互换?

Swift 5破坏了我的本机模块导出,并带有错误Swift类扩展和Swift类上的类别不允许具有+ load方法

Java扩展具有特定类型的超类的泛型方法

具有特定 Self 类型的 Swift 协议扩展

使用子类和超类引用访问实例方法

从超类调用子类方法

构造扩展具有自己的构造函数的超类的对象

将子类转换为超类并调用两个类都具有的函数