无法将协议的通用关联类型的值转换为预期的参数类型
Posted
技术标签:
【中文标题】无法将协议的通用关联类型的值转换为预期的参数类型【英文标题】:Cannot convert value of generic associated type of protocol to expected argument type 【发布时间】:2018-07-02 15:40:32 【问题描述】:为了学习 Swift 泛型,我编写了一个函数来创建一个 tableView 数据源,即一个 2 维(节、行)元素数组。 元素类型应该是通用的,并且创建的数据源应该使用元素的唯一值进行初始化。
我声明了可能的元素类型采用的协议:
protocol UniqueInit
associatedtype T
static func uniqueInit() -> T
还有dataSource
函数。
这里,nrRowsInSection
是一个可变参数:给定的参数数量定义了部分的数量,而参数的值定义了相应部分中的行数。
static func dataSource<T: UniqueInit>(nrRowsInSection: Int...) -> [[T]]
var result: [[T]] = []
for nrRows in nrRowsInSection
var row: [T] = []
for _ in 0 ..< nrRows
row.append(T.uniqueInit())
result.append(row)
return result
此函数无法编译。声明
row.append(T.uniqueInit())
给出错误:
Argument type 'T.T' does not conform to expected type 'UniqueInit'
Cannot convert value of type 'T.T' (associated type of protocol 'UniqueInit') to expected argument type 'T' (generic parameter of static method 'dataSource(nrRowsInSection:)')
显然,static func uniqueInit()
被认为是错误的,但为什么呢?
正确的实现方式是什么?
【问题讨论】:
【参考方案1】:函数中的泛型T
和协议中的关联类型T
不同T
。在函数内部,T
指的是实现协议的类型,因此函数内部的关联类型是T.T
。您的数组和返回值必须使用T.T
。
这也意味着您需要为函数添加一个附加参数,因为 [[T.T]]
返回值不足以让编译器推断 T
是什么类型。
这应该可行(我将通用参数更改为U
,因为所有T
s 都令人困惑):
func dataSource<U: UniqueInit>(initializer: U.Type, nrRowsInSection: Int...) -> [[U.T]]
var result: [[U.T]] = []
for nrRows in nrRowsInSection
var row: [U.T] = []
for _ in 0 ..< nrRows
row.append(U.uniqueInit())
result.append(row)
return result
或者,您可以将您的函数定义为 UniqueInit
上的扩展,这样就不需要泛型:
extension UniqueInit
func dataSource(nrRowsInSection: Int...) -> [[T]]
var result: [[T]] = []
for nrRows in nrRowsInSection
var row: [T] = []
for _ in 0 ..< nrRows
row.append(Self.uniqueInit())
result.append(row)
return result
【讨论】:
感谢您的回答。我将简要检查您的建议。 我检查了你的第一个解决方案,它确实有效,谢谢!我现在明白了,我的实现中的 2 T 是不同的。【参考方案2】:看看下面的实现是否适合你。
protocol UniqueInit
static func uniqueInit() -> Self
func dataSource<T: UniqueInit>(nrRowsInSection: Int...) -> [[T]]
var result: [[T]] = []
for nrRows in nrRowsInSection
var row: [T] = []
for _ in 0 ..< nrRows
row.append(T.uniqueInit())
result.append(row)
return result
我认为上面dataSource实现中的T应该换成UniqueInit。
【讨论】:
以上是关于无法将协议的通用关联类型的值转换为预期的参数类型的主要内容,如果未能解决你的问题,请参考以下文章
无法将类型“Int”的值转换为泛型中的预期参数类型“Int”
Swift:无法将“NSDate”类型的值转换为预期的参数类型“NSDateComponents”