通用对象的约束扩展与类型

时间:2016-07-05 21:17:29

标签: ios swift generics protocols class-extensions

我正在尝试对泛型类进行扩展,该泛型类受泛型类型的约束。这是我认为应该工作的代码的简化:

struct Thing<T> {
    var value: T
}

struct ContainsStringThing {
    var stringThing: Thing<String>
}

extension Thing where T == String {                           // <-- Error location
    func containedStringThing() -> ContainsStringThing {
        return ContainsStringThing(stringThing: value)
    }
}

但是,我收到以下错误消息:

  

相同类型的要求使得通用参数&#39; T&#39;非通用

我搜索了一种修复此问题的方法,并找到了使用协议约束扩展名而不是类型link to article的建议。完成后我最终得到了这个:

protocol StringProtocol { }

struct Thing<T> {
    var value: T
}

struct ContainsStringThing {
    var stringThing: Thing<StringProtocol>
}

extension Thing where T: StringProtocol {
    func containedStringThing() -> ContainsStringThing {
        return ContainsStringThing(stringThing: self)         // <-- Error location
    }
}

现在它确实让我限制了扩展名,但它显示了一条不同的错误消息:

  

无法转换类型的值&#39; Thing&lt; T&gt;&#39;预期参数类型&#39; Thing&lt; StringProtocol&gt;&#39;

现在它基本上知道T本身符合协议StringProtocol,但在引用整个对象Thing<T>时它并不知道。

是否有任何解决方法,或者我应该将其作为进化提案提交给swift邮件列表?

注意:所有代码都在操场上进行测试,您只需复制并粘贴即可试用。

1 个答案:

答案 0 :(得分:0)

作为一种解决方法,您可以使用self中的值创建Thing的新实例。

extension Thing where T: StringProtocol {
    func containedStringThing() -> ContainsStringThing {
        return ContainsStringThing(stringThing: Thing<StringProtocol>(value: self.value))
    }
}

在Swift 2.2中,这样的扩展约束意味着 containedStringThing()函数将可用于其值类型符合StringProtocol的Thing。

如果Swift编译器可以将 self.value 的类型推断为 StringProtocol ,那就太好了。在这种情况下你可以写 ContainsStringThing(stringThing: self)代替 ContainsStringThing(stringThing: Thing<StringProtocol>(value: self.value))。你一定要填写提案。