带有协议的swift泛型

5anewei6  于 2023-01-16  发布在  Swift
关注(0)|答案(3)|浏览(150)

我用泛型创建了一个函数

func sorted<T: MyProtocol>(array: [T]) -> [T] { ... }

想打电话

let array: [MyProtocol] = [...]
let sortedArray = sorted(array: array)

但是得到错误

Type 'any MyProtocol' cannot conform to 'MyProtocol'

我知道变量array是一个盒子,可以包含任何符合MyProtocol的东西,但是我怎么解决这个问题呢?我需要对任何MyProtocol排序
尝试过类似的东西,但不工作

func sorted<T: any MyProtocol>(array: [T]) -> [T] { ... }
eufgjt7s

eufgjt7s1#

我知道变量array是一个盒子,可以包含任何符合MyProtocol的东西。
这正是你的代码的问题所在,当你写let array: [MyProtocol]时,它不是一个采用MyProtocol协议的具体类型的数组,它实际上是一个**存在类型的数组,可以存储任何采用MyProtocol协议的对象,而这种存在类型本身并不采用该协议。
但是,当您编写泛型函数func sorted<T: MyProtocol>时,您特别将类型T约束为采用MyProtocol的某个类型。由于存在类型本身不采用协议,因此您收到了错误。
要解决这个问题,可以不约束函数sorted,而是让参数本身和返回值成为存在类型的数组:

func sorted(array: [MyProtocol]) -> [MyProtocol]

旁注,从Swift 5.6开始,存在类型的用法应该显式表示,所以你的array声明将变成:

let array: [any MyProtocol] = [...]

函数签名将变为:

func sorted(array: [any MyProtocol]) -> [any MyProtocol]
oxosxuxt

oxosxuxt2#

如果你想在Element的基础上给Array添加一个函数,你可以通过扩展数组...

extension Array where Element: MyProtocol {
  func sorted() -> [Element] {
    // put your sorting logic here that uses the `MyProtocol` properties.
  }
}

话虽如此...如果你能对符合你的MyProtocol的对象进行排序,那么那个协议也很可能符合Comparable
[Comparable]上已经有一个sorted函数(符合Comparable的对象数组),所以你不需要一个新函数。
要实现这一点,您可以将协议定义为...

protocol MyProtocol: Comparable {
}

这将为您的数组提供.sorted()函数。
可比性文件... https://developer.apple.com/documentation/swift/comparable

s71maibg

s71maibg3#

该错误消息指示数组变量中的元素类型any MyProtocol与排序函数的泛型约束MyProtocol中指定的类型不同。
在Swift中,any是所有类型都遵守的协议,所以any MyProtocol是同时遵守any和MyProtocol协议的类型。
要修复此错误,您可以将数组变量的类型更改为[MyProtocol],或将排序函数的约束更改为T:任何我的方案。

相关问题