Swift协议扩展方法用超类和子类调度 [英] Swift protocol extension method dispatch with superclass and subclass

查看:159
本文介绍了Swift协议扩展方法用超类和子类调度的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I found an interesting behaviour which seems like a bug...

根据以下文章描述的行为:

Based on the behaviour described the following articles:

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

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

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

The output is not what I expect, when I add SomeSuperclass, rather than directly adopting the protocol.

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

你知道这是一个bug还是设计?一位同事建议,混合继承和协议扩展可能无法按预期工作。我打算使用协议扩展来提供默认实现......如果我不能这样做,那么我很遗憾地必须将它标记为 @objc 并返回一个可选的协议。

Do you know if this is a bug, or by design? A colleague suggested perhaps mixing inheritance and protocol extensions might not work as expected. I was intending to use the protocol extension to provide a default implementation... if I can't do it, then I will sadly have to mark it @objc and go back to an optional protocol.

推荐答案

从帖子 Swift Bugs Future的幽灵,以下是发送的规则在帖子末尾提到的协议扩展。

From the post The Ghost of Swift Bugs Future, here are the rules for dispatch for protocol extensions that are mentioned at the end of the post.


  1. 如果变量的推断类型是协议:

  2. 并且该方法在原始协议中定义,然后调用
    运行时类型的实现,而不管
    是否在扩展中有默认实现。

  3. AND方法未在原始协议中定义,然后调用
    默认实现。

  4. ELSE IF t他推断变量的类型是类型THEN类型的实现被调用。

  1. IF the inferred type of a variable is the protocol:
  2. AND the method is defined in the original protocol THEN the runtime type’s implementation is called, irrespective of whether there is a default implementation in the extension.
  3. AND the method is not defined in the original protocol, THEN the default implementation is called.
  4. ELSE IF the inferred type of the variable is the type THEN the type’s implementation is called.

所以在你的情况下,你说的是method1 ()在协议中定义,并且已在子类中实现。但是你的超类正在采用协议,但它没有实现method1(),而子类只是继承自Superclass,并没有直接采用协议。这就是为什么我认为这是你调用foo.method1()的原因,它不会调用第1点和第1点所述的子类实现。 2。

So in your condition, you're saying that method1() is defined in the protocol and it has been implemented in the subclass. But your superclass is adopting the protocol but it is not implementing the method1() and subclass just inherits from the Superclass and doesn't adopt to the protocols directly. That's why I believe that is the reason when you call foo.method1(), it doesn't invoke the the subclass implementation as stated by point 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的解决方法是什么(似乎是是一个错误)是,您需要在超类中实现协议方法,然后您需要覆盖子类中的协议方法。 HTH

So what could be the workaround for this bug (which seems to be a bug) is that, you need to implement the protocol method in the superclass and then you need to override the protocol method in the sub class. HTH

这篇关于Swift协议扩展方法用超类和子类调度的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆