具有类绑定约束的泛型类不能通过类绑定协议进行参数化



我想要一个对对象的通用弱引用,并通过类绑定的协议对其进行参数化。

以下是在我的情况下不起作用的代码示例:

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()
}

因为这会导致限制。

您说的是:

final class Weak<Type> where Type: AnyObject {

所以您自己要求Type是一个类(因为这正是AnyObject的意思(。

协议是而不是类。这是一个协议。

这目前是不可能的,因为协议本身并不一致。协议不是一种类型;这是一种类型的配方。作为为什么这很难的最简单的例子,考虑一下这种情况:

protocol X {
init()
}
func f<T: X>(type: T.Type) -> T {
return type.init()
}
f(type: X.self)

这将创建一个类型为X的值,但会是这样吗?这是不允许的,阻止它的机制是协议本身不符合。这会以许多其他方式出现,你的例子就是其中之一。

其中一些问题将在更多的《泛型宣言》实施时得到解决,特别是《广义存在主义》一节,但目前你想要的是不可能的。你不能有"对某个未知事物的弱引用"。你需要知道那是什么。

这个问题的标准解决方案是一个盒子,而不是一个协议。有关示例,请参见弱阵列。

如果我理解你的问题,我设计这个解决方案

首先,我创建了一个名为WeakProtocolprotocol,这将是我们协议的基础

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更改为将AnyObjectWeak类扩展为Type:Protocol,就像这个一样

protocol Protocol: AnyObject {
func function()
}
final class A: Protocol {
func function() {}
}
final class Weak<Type> where Type: Protocol {
final private weak var property: Type?
init(property: Type) {
self.property = property
}
}
let a = A()
let something = Weak(property: a)

最新更新