use*_*806 3 generics init swift
我在创建方便的init方法时遇到问题,该方法随后在具有泛型类型参数的类上调用指定的init。这是Swift 3.1 XCode版本8.3.2(8E2002)游乐场
protocol A {
var items: [String] { get set }
func doSomething()
}
struct Section : A {
var items: [String] = []
func doSomething() {
print("doSomething")
items.forEach { print($0) }
}
}
class DataSource<T: A> {
var sections: [T]
init(sections: [T]) {
self.sections = sections
}
func process() {
sections.forEach { $0.doSomething() }
}
convenience init() {
var section = Section()
section.items.append("Goodbye")
section.items.append("Swift")
self.init(sections: [section])
}
}
/*: Client */
var section = Section()
section.items.append("Hello")
section.items.append("Swift")
let ds = DataSource(sections: [section])
ds.process()
Run Code Online (Sandbox Code Playgroud)
如果不存在便利初始化,则/ *:Client * /部分下面的代码将编译并执行而不会出现问题。如果我添加了便利初始化,则会出现以下编译错误:
cannot convert value of type '[Section]' to expected argument type '[_]'
self.init(sections: [section])
Run Code Online (Sandbox Code Playgroud)
我不认为这将是一个问题,因为在方便的初始化中,我正在创建一个Section结构,该结构实现协议A,该协议A满足DataSource类的一般约束。便利初始化正在执行与客户端代码相同的操作,但无法将[Section]转换为[A]。这是初始化排序问题吗?
通用占位符对给定通用类型的使用感到满意–因此,在您内部convenience init,您不能假定它T是Section。这是符合的任意具体类型A。
例如,调用方定义一个
struct SomeOtherSection : A {...}
Run Code Online (Sandbox Code Playgroud)
然后调用您的方便与初始化剂T是 SomeOtherSection。
在这种情况下,解决方法很简单,只需将它添加您的方便初始化器中的延伸DataSource,其中T被约束为被Section-因此允许你
打电话init(sections:)了[Section]:
extension DataSource where T == Section {
convenience init() {
var section = Section()
section.items.append("Goodbye")
section.items.append("Swift")
self.init(sections: [section])
}
}
// ...
// compiler will infer that T == Section here.
let ds = DataSource()
Run Code Online (Sandbox Code Playgroud)