swift - Swift 协议行为
问题描述
假设我在 Swift 中有协议 FooProtocol ,其中一种方法具有默认实现:
protocol FooProtocol {
func foo()
}
extension FooProtocol {
func foo() {
print("protocol")
}
}
和具有强制转换实例的类 FooClass:
class FooClass : FooProtocol {
func foo() {
print("class")
}
}
let A = FooClass() as FooProtocol
A.foo()
正如预期的那样,“class”将打印在控制台中。但是,如果我将协议的 foo() 方法设为可选 - 将改为打印“协议”。
@objc protocol FooProtocol {
@objc optional func foo()
}
但是如果我调用 A.foo?() 而不是 A.foo() - "class" 将再次打印。
我想知道,仅出于理论目的,这里到底发生了什么?任何解释表示赞赏。
解决方案
optional
没有可选链接就不能调用协议方法。即如果你注释掉
extension FooProtocol {
func foo() {
...
你尝试调用A.foo()
,你会得到一个编译错误:
可选类型 '(() -> ())?' 的值 必须解包为 '() -> ()' 类型的值
如您所见,可选的签名甚至与非可选的不同。因此,通过调用A.foo()
,您不是在调用您实现的方法,而是直接调用默认协议实现。
这也是有道理的,因为使用 Objective C进行插值的主要原因@objc optional
是默认协议实现不可见。因此,依赖于 objc 函数的协议函数会在 swift 和 Objective c 上产生不同的结果,这是不希望的。
我不能说optional
在同一功能上同时使用默认协议实现是否存在任何漏洞。但问题是:你真的需要它吗?
如果你关心插值,你需要为 Swift 和 Objective c 提供相同的解决方案,这意味着你需要基本的协议实现,Swift 和 objc 都可以继承
如果您不需要插值,则实际上不需要可选,并且可以单独依赖默认协议实现。
推荐阅读
- python - OSError: [Errno 22] 尝试创建 txt 文件时参数无效
- python - Pandas:根据较长字符串列表中的匹配项展开列字符串值
- sql - 使用 select 语句仅从 nvarchar 列输出某些值
- node.js - 关闭浏览器选项卡或窗口时,Socket.io 连接未正确断开
- asp.net-mvc - PagedListRenderOptions :如何添加 FunctionToTransformEachPageLink 页面链接类?
- javascript - tooltipster - 在多个工具提示上使用一个功能 - origin.helper 或一个或多个工具提示的问题已经存在
- dax - 如何使用 dax 基于左连接在表中添加列
- content-management-system - Publii previousPost 和 nextPost 不起作用
- python - 初始化 tkinter gui 导致主线程不在主循环中
- windows - 如何在不先连接到 VPN 的情况下通过 PowerShell 为 VPN 连接指定 DNS 服务器?