我想对一个对象有一个通用的弱引用,并通过一个类绑定的协议对其进行参数化。
这是在我的情况下不起作用的代码示例:
protocol Protocol: class { // also written as `protocol Protocol: AnyObject {`
func function()
}
final class A: Protocol {
func function() {}
}
final class Weak<Type> where Type: AnyObject {
final private weak var property: Type?
init(property: Type) {
self.property = property
}
}
let a = A()
let something = Weak<Protocol>(property: a) // error: 'Weak' requires that 'Protocol' be a class type
我在最后一行:'Weak' requires that 'Protocol' be a class type
上遇到错误。
由于Protocol
始终是class
类型(与AnyObject
相同),编译器不应该这样吗?
是否可以使用Swift 4解决该问题?
如果不是,这是可以在swift的未来版本中解决的限制,还是类型系统不允许发生的事情?
不接受的解决方案是对协议声明使用@objc
,如下所示:
@obc protocol Protocol: class {
func function()
}
因为这会带来局限性。
答案 0 :(得分:2)
您在说:
final class Weak<Type> where Type: AnyObject {
因此您自己需要将Type用作类(因为正是AnyObject的意思)。
协议不是 类。这是一个协议。
答案 1 :(得分:0)
由于协议不符合自身,目前这是不可能的。协议不是一种类型。这是一种类型的食谱。作为解决此问题的最简单示例,请考虑以下情况:
protocol X {
init()
}
func f<T: X>(type: T.Type) -> T {
return type.init()
}
f(type: X.self)
这将创建类型X
的值,但是那样吗?这是不允许的,阻止它的机制是协议不符合自身。这以许多其他方式出现,您的示例就是其中之一。
当更多的Generics Manifesto被实现时,某些问题将得到解决,特别是“通用存在”部分,但目前尚无法实现。您不能有“对某些未知事物的弱引用”。您需要知道那是什么。
此问题的标准解决方案是盒子,而不是协议。有关示例,请参见Weak Arrays。
答案 2 :(得分:0)
如果我了解您的问题,我会设计此解决方案
首先,我创建了一个名为protocol
的{{1}},这将是我们的协议基础
WeakProtocol
更改协议以扩展此新protocol WeakProtocol : AnyObject {}
WeakProtocol
在您的protocol Protocol: WeakProtocol {
func function()
}
类之后,您需要应用一个Weak
类型的示例
WeakProtocol
现在要实现您不需要说协议,因为构造函数会收到协议。
完整的代码是
final class Weak<Type> where Type: WeakProtocol {
final private weak var property: Type?
init(property: Type) {
self.property = property
}
}
您也只能将protocol WeakProtocol : AnyObject {}
protocol Protocol: WeakProtocol {
func function()
}
final class A: Protocol {
func function() {}
}
final class Weak<Type> where Type: WeakProtocol {
final private weak var property: Type?
init(property: Type) {
self.property = property
}
}
let a = A()
let something = Weak(property: a)
更改为将Protocol
和AnyObject
类扩展到Weak
,就像这样
Type:Protocol