带有 where 子句的 Swift 数组扩展不适用于子协议(protocol)

标签 swift swift-extensions swift-protocols

我写了一些我认为应该在 Swift 2 (Xcode 7b4) 中工作的代码,但它没有编译。我希望得到一些关于我正在尝试做的事情是否应该有效的想法。

考虑这个示例 Array 扩展:

extension Array where Element: AnyObject {
    mutating func appendUniqueInstance(e: Element) {
        for element in self {
            if (element === e) {
                return
            }
        }

        self.append(e)
    }
}

首先,元素为AnyObject 的数组是什么意思?基本上我是说数组应该包含一组异构的非值类型对象,可以比较实例相等性 (===)。

示例函数 appendUniqueInstance() 仅将一个元素插入到数组中(如果它不在数组中)。这类似于 Set insert() 操作,但显然提供了排序并且(更重要的是)不强加 Set 的同类类型要求(通过 EquatableSelf 的使用)。

如果我现在定义一个协议(protocol) P 和一个实现 P 的类 C:

protocol P : AnyObject {}

class C : P {}

并实例化一个C:

让 c = C()

那么这些非常明显的事情是真的:

let cIsAnyObject = c as AnyObject   // ok
let cIsP = c as P                   // ok

现在我可以执行以下操作:

var a1 = [AnyObject]()              // []

a1.appendUniqueInstance(c)          // [c]
a1.appendUniqueInstance(c)          // [c]

到目前为止一切顺利,但现在是问题案例:

var a2 = [P]()

a2.append(c)                        // ok, -> [c]

// Compiler error: Cannot invoke 'appendUniqueInstance' with an argument list of type '(C)'
a2.appendUniqueInstance(c)

在这里,a2 被键入为 P 的数组,因此附加 的实例应该是完全有效的事情P,确实 a2.append(c) 行如我们所料。

然而,调用Array 扩展函数appendUniqueInstance() 会产生编译器错误。

据我所知,编译器似乎对可以传递给 appendUniqueInstance() 的内容感到困惑,并且没有意识到(或出于某种原因允许)C(通过 P)是一个 AnyObject

顺便说一句,如果我将 P 声明为:

@objc 协议(protocol) P : AnyObject {}

然后一切都编译得很好,但我还必须确保协议(protocol) P 中的所有内容都符合 @objc,这不是我想要的。

所以,在所有这一切之后,我的问题是:这看起来应该可行吗?我希望这不仅仅是一些声明语法错误的情况,但我想如果是的话我会很高兴。

最佳答案

如果您命令单击AnyObject,您会注意到它是一个符合@objc 的协议(protocol)。所以我猜这就是它要求使用@objc 的原因。我注意到,如果我们将 C 设为 NSObject 的子类,则无需显式地实现 P 中的方法以符合 @objc

@objc protocol P : AnyObject {
    func hey()
}

class C : NSObject, P {
    func hey() {
        print("hey")
    }
}

关于带有 where 子句的 Swift 数组扩展不适用于子协议(protocol),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31710737/

相关文章:

ios - UIScrollView: View 不会自动滚动

ios - HeaderView 按钮以编程方式转到另一个 View Controller

ios - 推送到 View Controller 时,导航栏会覆盖我的内容

ios - 如何根据应用程序在 Swift 中运行的设备自动调整标题组件的高度

objective-c - Swift Extension 无法向 Objective-C 类添加重载方法

ios - 如何将变量从类传递到类正在使用的对象的扩展?

swift - some View 作为方法/初始化器的输入参数

swift - 自身,协议(protocol)扩展和非最终类

swift - ARCore 是否具有 ARKit 的 "guard let planeAnchor"的语义等价物?

Swift Decodable,Endpoint返回完全不同的类型