博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Swift protocol extension method is called instead of method implemented in subclass
阅读量:6008 次
发布时间:2019-06-20

本文共 3681 字,大约阅读时间需要 12 分钟。

Swift protocol extension method is called instead of method implemented in subclass

 

protocol MyProtocol {

    func methodA()

    func methodB()

}

 

extension MyProtocol {

    func methodA() {

        print("Default methodA")

    }

 

    func methodB() {

        methodA()

    }

}

 

// Test 1

class BaseClass: MyProtocol {

 

}

 

class SubClass: BaseClass {

    func methodA() {

        print("SubClass methodA")

    }

}

 

 

let object1 = SubClass()

object1.methodB()

//

 

// Test 2

class JustClass: MyProtocol {

    func methodA() {

        print("JustClass methodA")

    }

}

 

let object2 = JustClass()

object2.methodB()

//

// Output

// Default methodA

// JustClass methodA

 

This is just how protocols currently dispatch methods.

A protocol witness table (see for more info) is used in order to dynamically dispatch to implementations of protocol requirements upon being called on a protocol-typed instance. All it is, is really just a listing of the function implementations to call for each requirement of the protocol for a given conforming type.

Each type that states its conformance to a protocol gets its own protocol witness table. You'll note that I said "states its conformance", and not just "conforms to". BaseClass gets its own protocol witness table for conformance to MyProtocol. However SubClass does not get its own table for conformance to MyProtocol – instead, it simply relies on BaseClass's. If you moved the

: MyProtocol down to the definition of SubClass, it would get to have its own PWT.

So all we have to think about here is what the PWT for BaseClass looks like. Well, it doesn't provide an implementation for either of the protocol requirements methodA() or methodB() – so it relies on the implementations in the protocol extension. What this means is that the PWT for BaseClass conforming to MyProtocol just contains mappings to the extension methods.

So, when the extension methodB() method is called, and makes the call out to methodA(), it dynamically dispatches that call through the PWT (as it's being called on a protocol-typed instance; namely self). So when this happens with a SubClass instance, we're going through BaseClass's PWT. So we end up calling the extension implementation of methodA(), regardless of the fact that SubClass provides an implementation of it.

Now let's consider the PWT of JustClass. It provides an implementation of methodA(), therefore its PWT for conformance to MyProtocol has that implementation as the mapping for methodA(), as well as the extension implementation for methodB(). So when methodA() is dynamically dispatched via its PWT, we end up in its implementation.

As I say , this behaviour of subclasses not getting their own PWTs for protocols that their superclass(es) conform to is indeed somewhat surprising, and has been . The reasoning behind it, as Swift team member Jordan Rose says in the comments of the bug report, is

Therefore if this was the behaviour, already-compiled subclasses would lack any PWTs from superclass conformances that were added after the fact in another module, which would be problematic.

 

As others have already said, one solution in this case is to have BaseClass provide its own implementation of methodA(). This method will now be in BaseClass's PWT, rather than the extension method.

Although of course, because we're dealing with classes here, it won't just be BaseClass's implementation of the method that's listed – instead it will be a that then dynamically dispatches through the class' vtable (the mechanism by which classes achieve polymorphism). Therefore for a SubClass instance, we'll wind up calling its override of methodA().

 

https://stackoverflow.com/questions/44703205/swift-protocol-extension-method-is-called-instead-of-method-implemented-in-subcl

转载地址:http://krsmx.baihongyu.com/

你可能感兴趣的文章
用python爬取app照片
查看>>
ASP.NET状态管理
查看>>
软件工程中的瀑布模型和敏捷模型
查看>>
不做7件事,提高生产力
查看>>
PS小技巧之完美抠图
查看>>
一个Oracle触发器的示例
查看>>
《Photoshop CS5 The Missing Manual》 - 书摘精要
查看>>
HSQLDB 安装与使用
查看>>
Oracle 字符串分割排序冒泡算法
查看>>
深度学习与神经网络
查看>>
李小龙教给我们的敏捷开发之道
查看>>
windows 程序设计的一些总结
查看>>
细数AutoLayout以来UIView和UIViewController新增的相关API<转写>
查看>>
[转]SqlServer 表分区详细介绍
查看>>
02 栈(Stack)
查看>>
春季学期第六周作业
查看>>
字符串交叉插入
查看>>
项目总结
查看>>
codeforces #139 A dice tower
查看>>
Integer.valueOf与Integer.parseInt的小疑惑
查看>>