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

时间:2018-07-26 14:31:52

标签: swift generics swift-protocols

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

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

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

因为这会带来局限性。

3 个答案:

答案 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) 更改为将ProtocolAnyObject类扩展到Weak,就像这样

Type:Protocol