如何解决使用 where 子句创建 Swift 扩展,该子句过滤采用泛型的结构
我正在尝试在 Set
上创建一个使用 where 子句的扩展,以便它仅适用于我拥有的接受泛型的结构。但是我一直遇到关于它的错误,希望在结构中定义泛型
在此示例中,我收到以下错误,编译器提示建议我使用 <Any>
:对泛型类型“Test”的引用需要 <...>
struct Test<T> {
var value : T
func printIt() {
print("value")
}
}
extension Set where Element == Test {
}
但是,当我在结构中使用 <Any>
时,我收到此错误:相同类型的约束类型“测试”不符合所需的协议“Equatable” >
extension Set where Element == Test<Any> {
}
关于如何让 where 子句接受我在泛型中使用的任何类型的测试结构的任何建议?
感谢您的帮助
解决方法
这是 Swift 类型系统的限制。没有具体的类型参数就无法谈论泛型类型,即使这些类型参数与类型的使用无关。对于这种特殊情况(所有可能的类型参数的扩展),我认为没有任何深层问题可以阻止它。它是 parameterized extensions 的一个更简单的版本,这是一个理想的功能。只是不支持 (though there is an implementation in progress)。
今天解决这个问题的标准方法是使用协议。
首先,进行一些与您的问题无关的清理工作(您可能已经知道了)。您的示例要求测试为 Hashable
:
struct Test<T: Hashable>: Hashable {
var value : T
func printIt() {
print("value")
}
}
制定一个协议,需要任何你想要的扩展部分,并使测试符合:
protocol PrintItable {
func printIt()
}
extension Test: PrintItable {}
然后使用协议而不是类型:
extension Set where Element: PrintItable {
func printAll() {
for item in self { item.printIt() }
}
}
let s: Set<Test<Int>> = [Test(value: 1)]
s.printAll() // value
就您收到的错误消息再做一个说明。第一个错误,要求你添加 Any 实际上只是抱怨 Swift 不能谈论非参数化泛型,并在它不知道建议什么类型时建议它是后备类型:Any。
但是 Set<Any>
不是“任何类型的 Set”。它是一个 Set,其中 Element == Any。所以 Any 必须是可哈希的,这是不可能的。并且 Set<Int>
不是 Set<Any>
的子类型。有完全不同的类型。所以这些错误有点令人困惑,会让你走上一条毫无帮助的道路。
这是不可能的。 where 子句需要特定的数据类型,除非我指定更具体的内容,例如 Test
,否则简单地传递 Test<String>
是行不通的。
感谢 Joakim 和 flanker 在评论中回答问题
,如果您想使用 where 子句为 Set 添加扩展,您的测试必须确认Hashable 协议。 您的结构必须如下所示。
struct Test<T: Hashable> : Hashable {
var value : T
func printIt() {
print("value")
}
func hash(into hasher: inout Hasher) {
hasher.combine(value.hashValue)
}
}
所以你不能使用Any作为你的扩展,你必须指定确认Hashable协议的类型.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。