Swift 协议中的泛型
Swift generics in protocols
用 swift 解决以下示例的合适方法是什么?
我知道由于类型擦除,您不能在构造函数中将 StructB
分配给 item2
。在 Java 等其他语言中,我会通过在 Container
结构中没有通用 class 参数 T
来解决问题,但是让vars item
和 item2
只是 ProtocolA
的类型(如 var item2: ProtocolA
)。
这是swift不允许的:协议'ProtocolA'只能作为泛型约束,因为它有Self或关联类型要求
我完成了 swift 文档中关于泛型的 this 部分,但到目前为止我无法针对我的简单问题调整解决方案:
protocol ProtocolA {
associatedtype B
func foo() -> B
}
struct StructA: ProtocolA {
typealias B = String
func foo() -> String {
"Hello"
}
}
struct StructB: ProtocolA {
typealias B = Double
func foo() -> Double {
0.0
}
}
struct Container<T: ProtocolA> {
var item: T
var item2: T
init(item: T) {
self.item = item
self.item2 = StructB() // err: Cannot assign value of type 'StructB' to type 'T'
}
}
我还想知道如果我根本不想为容器结构指定泛型类型参数,解决方案会是什么样子。这样我就可以写下:
func test() {
let container = Container(StructA()) // no type given
}
做你想做的事情的唯一方法是:
struct Container<T: ProtocolA,U: ProtocolA> {
var item: T
var item2: U
init(item: T, item2: U) {
self.item = item
self.item2 = item2
}
}
对于描述的问题,答案很简单:
struct Container<T: ProtocolA> {
var item: T
var item2: StructB // This isn't T; you hard-coded it to StructB in init
init(item: T) {
self.item = item
self.item2 = StructB()
}
}
let container = Container(item: StructA()) // works as described
我觉得这个问题有更深层次的东西,这就是为什么 Alexander 要求提供更多背景信息。正如所写,问题的答案似乎太简单了,所以我们中的一些人认为还有更多您没有解释的内容,我们希望避免一轮“这是答案”,然后是“这不是我的意思”。
如您所写,您试图强制 item
和 item2
具有相同的类型。这显然不是你的意思,因为 T
是由调用者给出的,而 item2
总是 StructB(它不必等于 T
,正如错误所解释的那样)。
你打算用另一种方式调用这段代码吗?目前还不清楚调用 foo()
的代码会是什么样子。您是否有其他未在问题中解释的方式来初始化 Container?
也许您想要两种不同的类型,而您只想将 StructB 作为默认值?在那种情况下,它看起来像(基于 Ptit Xav 的回答):
struct Container<T: ProtocolA, U: ProtocolA> {
var item: T
var item2: U
// Regular init where the caller decides T and U
init(item: T, item2: U) {
self.item = item
self.item2 = item2
}
// Convenience where the caller just decides T and U is default
init(item: T) where U == StructB {
self.init(item: item, item2: StructB())
}
}
where U == StructB
允许您为 U 设置默认类型。
用 swift 解决以下示例的合适方法是什么?
我知道由于类型擦除,您不能在构造函数中将 StructB
分配给 item2
。在 Java 等其他语言中,我会通过在 Container
结构中没有通用 class 参数 T
来解决问题,但是让vars item
和 item2
只是 ProtocolA
的类型(如 var item2: ProtocolA
)。
这是swift不允许的:协议'ProtocolA'只能作为泛型约束,因为它有Self或关联类型要求
我完成了 swift 文档中关于泛型的 this 部分,但到目前为止我无法针对我的简单问题调整解决方案:
protocol ProtocolA {
associatedtype B
func foo() -> B
}
struct StructA: ProtocolA {
typealias B = String
func foo() -> String {
"Hello"
}
}
struct StructB: ProtocolA {
typealias B = Double
func foo() -> Double {
0.0
}
}
struct Container<T: ProtocolA> {
var item: T
var item2: T
init(item: T) {
self.item = item
self.item2 = StructB() // err: Cannot assign value of type 'StructB' to type 'T'
}
}
我还想知道如果我根本不想为容器结构指定泛型类型参数,解决方案会是什么样子。这样我就可以写下:
func test() {
let container = Container(StructA()) // no type given
}
做你想做的事情的唯一方法是:
struct Container<T: ProtocolA,U: ProtocolA> {
var item: T
var item2: U
init(item: T, item2: U) {
self.item = item
self.item2 = item2
}
}
对于描述的问题,答案很简单:
struct Container<T: ProtocolA> {
var item: T
var item2: StructB // This isn't T; you hard-coded it to StructB in init
init(item: T) {
self.item = item
self.item2 = StructB()
}
}
let container = Container(item: StructA()) // works as described
我觉得这个问题有更深层次的东西,这就是为什么 Alexander 要求提供更多背景信息。正如所写,问题的答案似乎太简单了,所以我们中的一些人认为还有更多您没有解释的内容,我们希望避免一轮“这是答案”,然后是“这不是我的意思”。
如您所写,您试图强制 item
和 item2
具有相同的类型。这显然不是你的意思,因为 T
是由调用者给出的,而 item2
总是 StructB(它不必等于 T
,正如错误所解释的那样)。
你打算用另一种方式调用这段代码吗?目前还不清楚调用 foo()
的代码会是什么样子。您是否有其他未在问题中解释的方式来初始化 Container?
也许您想要两种不同的类型,而您只想将 StructB 作为默认值?在那种情况下,它看起来像(基于 Ptit Xav 的回答):
struct Container<T: ProtocolA, U: ProtocolA> {
var item: T
var item2: U
// Regular init where the caller decides T and U
init(item: T, item2: U) {
self.item = item
self.item2 = item2
}
// Convenience where the caller just decides T and U is default
init(item: T) where U == StructB {
self.init(item: item, item2: StructB())
}
}
where U == StructB
允许您为 U 设置默认类型。