swift 便利初始化和通用 class
swift convenience init and generic class
我在创建方便的 init 方法时遇到问题,该方法随后使用泛型类型参数调用 class 上的指定 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([=12=]) }
}
}
class DataSource<T: A> {
var sections: [T]
init(sections: [T]) {
self.sections = sections
}
func process() {
sections.forEach { [=12=].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()
如果不存在 convenience init,那么 /*:Client */ 部分下的代码将编译和执行,不会出现问题。如果我添加方便的 init,我会得到以下编译错误:
cannot convert value of type '[Section]' to expected argument type '[_]'
self.init(sections: [section])
我不认为这会是个问题,因为在方便的初始化中我创建了一个 Section 结构,它实现了满足数据源 class 上的通用约束的协议 A。 convenience init 正在执行与客户端代码相同的操作,但它无法将 [Section] 转换为 [A]。这是初始化顺序问题吗?
通用占位符对给定通用类型的使用感到满意 – 因此在您的 convenience init
中,您 不能假设 T
是一个 Section
。它是符合 A
.
的任意具体类型
例如,调用者定义一个
是完全合法的
struct SomeOtherSection : A {...}
然后调用您的便利初始化器 T
为 SomeOtherSection
。
这种情况下的解决方案很简单,您只需在 DataSource
的扩展中添加您的便利初始化程序,其中 T
被限制为 Section
- 因此允许您
用 [Section]
调用 init(sections:)
:
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()
我在创建方便的 init 方法时遇到问题,该方法随后使用泛型类型参数调用 class 上的指定 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([=12=]) }
}
}
class DataSource<T: A> {
var sections: [T]
init(sections: [T]) {
self.sections = sections
}
func process() {
sections.forEach { [=12=].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()
如果不存在 convenience init,那么 /*:Client */ 部分下的代码将编译和执行,不会出现问题。如果我添加方便的 init,我会得到以下编译错误:
cannot convert value of type '[Section]' to expected argument type '[_]'
self.init(sections: [section])
我不认为这会是个问题,因为在方便的初始化中我创建了一个 Section 结构,它实现了满足数据源 class 上的通用约束的协议 A。 convenience init 正在执行与客户端代码相同的操作,但它无法将 [Section] 转换为 [A]。这是初始化顺序问题吗?
通用占位符对给定通用类型的使用感到满意 – 因此在您的 convenience init
中,您 不能假设 T
是一个 Section
。它是符合 A
.
例如,调用者定义一个
是完全合法的struct SomeOtherSection : A {...}
然后调用您的便利初始化器 T
为 SomeOtherSection
。
这种情况下的解决方案很简单,您只需在 DataSource
的扩展中添加您的便利初始化程序,其中 T
被限制为 Section
- 因此允许您
用 [Section]
调用 init(sections:)
:
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()