受其他泛型参数约束的泛型参数

Posted

技术标签:

【中文标题】受其他泛型参数约束的泛型参数【英文标题】:Generic parameter constrained by other generic parameter 【发布时间】:2015-05-23 21:50:05 【问题描述】:

由于 Swift 缺乏协方差,我需要一些解决方法。我来自 Java 世界,所以我本能地尝试创建从一种类型到另一种泛型类型的约束。

所以我写了以下类:

class Factory<T: AnyObject> 
    let factoryClosure: () -> T

    init(closure: () -> T) 
        factoryClosure = closure
    

    init<CHILD: T>(childFactory: Factory<CHILD>) 
        factoryClosure =  () -> T in
            return otherFactory.create()
        
    

    func create() -> T 
        return factoryClosure()
    

我希望这可以正常工作。我定义了TCHILD 应该是T 的子类。然而,Swift 编译器不同意并在init&lt;CHILD: T&gt; 行显示以下错误。

从非协议、非类类型'T'继承

我也尝试了不同场景下的泛型参数继承。将以下方法添加到类中(并删除导致编译错误的 init)。

func to<OTHER where OTHER: AnyObject, T: OTHER>() 


这会产生基本相同的输出。

类型“T”被限制为非协议类型“OTHER”

任何我可能工作的东西都没有,并以类似的错误消息结束。这是 Swift 中的错误吗?还是我错过了什么?或者它是 Swift 的一个特性,永远不会像我想的那样工作?

【问题讨论】:

您真正想要实现的目标是什么?实际目标是,而不是一些试图实现所述未说明目标的代码。 我想要实现的目标是有一些东西可以让我解决缺少协方差的问题(如果我没记错的话)。在 Java 中,我将使用 Factory&lt;? extends MyObject&gt; 并可以传入 Factory 的任何实例,该实例的类型参数为 MyObject 或其子项。 这听起来仍然是手段而不是目的。实际目标是什么? 对,对不起,我一开始没有找到你。目标是某种依赖注入。我想将依赖项作为初始化参数。实例本身或我可以稍后调用以获取实例的工厂。问题出在后者,因为当我有init(someFactory: Factory&lt;Some&gt; 时,我无法通过Factory&lt;MockSome&gt; typhoonframework.org 是一个依赖注入框架 【参考方案1】:

如果你想传递任何Factory&lt;T&gt;,其中T 的类型是AnyObject,你只需要写:

init(childFactory: Factory<T>) 
    factoryClosure =  () -> T in
        return otherFactory.create()
    

因为 T 会自动受到您的类的约束。

【讨论】:

这不会解决问题,因为您只能传入Factory&lt;T&gt; 而不能传入Factory&lt;Z&gt;,其中ZT 的子类。 我认为这解决了你的问题,因为如果ZT 的子类,它也是AnyObject 类型。因此您也可以传递Factory&lt;Z&gt;T 只是符合AnyObject 的类型的占位符) 在上下文中,T 已经受您正在创建的类的约束。因此,如果您这样做let zFactory = Factory&lt;Z&gt;() return Z() ; let tFactory = Factory&lt;T&gt;(childFactory: zFactory),它将无法正常工作。

以上是关于受其他泛型参数约束的泛型参数的主要内容,如果未能解决你的问题,请参考以下文章

Kotlin的泛型约束

C#的泛型的类型参数可以有带参数的构造函数的约束方式吗?

TypeScript 条件类型的映射与受约束的泛型不同吗?

将 is 运算符与不受约束的泛型一起使用

Java的泛型约束和限制

lua不支持的泛型方法