要学习Swift泛型,我编写了一个函数来创建tableView数据源,即元素的2维(节,行)数组。 元素类型应该是通用的,并且应该使用元素的唯一值来初始化创建的数据源。
我声明了可能的元素类型采用的协议:
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">mydomain.com</domain>
<pin-set>
<pin digest="SHA-256">@string/pin</pin>
<pin digest="SHA-256">@string/pin_fallback</pin>
</pin-set>
<trustkit-config enforcePinning="true" disableDefaultReportUri="true">
</trustkit-config>
</domain-config>
</network-security-config>
和res/values/strings.xml
函数。
这里的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())
被认为是错误的,但是为什么呢?
正确的实现方法是什么?
答案 0 :(得分:2)
函数中的通用T
与协议中的关联类型T
不同T
。在函数内部,T
指的是实现协议的类型,因此,关联类型为函数内部的T.T
。您的数组和返回值必须使用T.T
。
这也意味着您需要为函数添加一个附加参数,因为[[T.T]]
返回值不足以使编译器推断T
是什么类型。
这应该可以工作(我将通用参数更改为U
,因为所有T
令人困惑):
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
}
}
答案 1 :(得分:0)
看看下面的实现是否适合您。
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。