Swift 带有 where 子句的数组扩展不适用于子协议
Swift Array extension with where clause doesn't work on sub-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
的同构类型要求(通过 Equatable
使用Self
).
如果我现在定义一个协议 P
和一个实现 P
:
的 class C
protocol P : AnyObject {}
class C : P {}
并实例化一个 C
:
let 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
的数组,因此对 append
P
的实例进行操作应该是完全有效的,并且a2.append(c)
行确实如我们所料。
但是调用 Array
扩展函数 appendUniqueInstance()
会产生编译器错误。
据我所知,编译器似乎对可以传递给 appendUniqueInstance()
的内容感到困惑,并且没有意识到(或出于某种原因允许)C
(通过 P
) 是一个 AnyObject
.
顺便说一句,如果我将 P
声明为:
@objc protocol P : AnyObject {}
然后一切都编译得很好,但我还必须确保协议 P
中的一切都符合 @objc
,这不是我想要的。
所以,在这一切之后,我的问题是:这看起来应该有用吗?我希望这不仅仅是一些声明语法错误的情况,但我想如果是的话我会很高兴。
如果您命令单击 AnyObject
,您会注意到它是一个符合@objc 的协议。所以我猜这就是它要求使用@objc 的原因。我注意到,如果我们将 C 设为 NSObject 的子类,则无需显式实现 P
中的方法以符合 @objc
@objc protocol P : AnyObject {
func hey()
}
class C : NSObject, P {
func hey() {
print("hey")
}
}
我写原始问题时编译器报告的错误似乎只是误导,我试图获得的功能不受(现在仍然不)支持 Swift .
使用 Xcode 8.2.1 和 Swift 3 会报告更准确的错误:
// error: using 'P' as a concrete type conforming
// to protocol 'AnyObject' is not supported
a2.appendUniqueInstance(c)
我写了一些代码,我认为 应该 在 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
的同构类型要求(通过 Equatable
使用Self
).
如果我现在定义一个协议 P
和一个实现 P
:
C
protocol P : AnyObject {}
class C : P {}
并实例化一个 C
:
let 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
的数组,因此对 append
P
的实例进行操作应该是完全有效的,并且a2.append(c)
行确实如我们所料。
但是调用 Array
扩展函数 appendUniqueInstance()
会产生编译器错误。
据我所知,编译器似乎对可以传递给 appendUniqueInstance()
的内容感到困惑,并且没有意识到(或出于某种原因允许)C
(通过 P
) 是一个 AnyObject
.
顺便说一句,如果我将 P
声明为:
@objc protocol P : AnyObject {}
然后一切都编译得很好,但我还必须确保协议 P
中的一切都符合 @objc
,这不是我想要的。
所以,在这一切之后,我的问题是:这看起来应该有用吗?我希望这不仅仅是一些声明语法错误的情况,但我想如果是的话我会很高兴。
如果您命令单击 AnyObject
,您会注意到它是一个符合@objc 的协议。所以我猜这就是它要求使用@objc 的原因。我注意到,如果我们将 C 设为 NSObject 的子类,则无需显式实现 P
中的方法以符合 @objc
@objc protocol P : AnyObject {
func hey()
}
class C : NSObject, P {
func hey() {
print("hey")
}
}
我写原始问题时编译器报告的错误似乎只是误导,我试图获得的功能不受(现在仍然不)支持 Swift .
使用 Xcode 8.2.1 和 Swift 3 会报告更准确的错误:
// error: using 'P' as a concrete type conforming
// to protocol 'AnyObject' is not supported
a2.appendUniqueInstance(c)