struct Lock<Element: Hashable> {
var element: Element
init(_ element: Element, _ args:[Lock<Element>]? = nil) {
self.element = element
}
}
是否可以修改这种结构,以便能够在参数中使用不同的Element
类型调用init()?
Lock("element", [Lock("100")])
没关系
Lock("element", [Lock(100)])
这会导致错误:无法转换类型&#39; Int&#39;预期参数类型&#39;锁定&lt; _&gt;&#39;
答案 0 :(得分:1)
您有2个选项可以执行此操作。
改进@ Cristik的答案的简单解决方案是让另一个初始化者不期望另一个通用参数:
struct Lock<Element> {
var element: Element
init(_ element: Element) {
self.element = element
}
init<T>(_ element: Element, _ args: [Lock<T>]?) {
self.init(element)
}
}
然后,您可以获得上面所需的代码,但却丢失了Element
符合Hashable
的信息。
您的第二个选择是使用protocol
创建associatedtype
。使用具有2 init
s的类似技巧,除了明确定义类型外,您可以执行相同的操作:
protocol Lock {
associatedtype Element
init(_ element: Element)
init<T>(_ element: Element, _ args: [T]?) where T: Lock
}
struct HashableLock<H: Hashable>: Lock {
typealias Element = H
var element: Element
init(_ element: Element) {
self.element = element
}
init<T>(_ element: Element, _ args: [T]?) where T: Lock {
self.init(element)
}
}
struct IntLock: Lock {
typealias Element = Int
var element: Int
init(_ element: Int) {
self.element = element
}
init<T>(_ element: Int, _ args: [T]?) where T: Lock {
self.init(element)
}
}
然后你可以创建这样的锁:
let stringStringLock = HashableLock("element", [HashableLock("100")])
let stringIntLock = HashableLock("element", [IntLock(100)])
第一个版本更清洁,但更具限制性。这取决于您使用哪一个,取决于您的需求。
答案 1 :(得分:0)
这不可能。
原因是Element
被分配给init
中用于元素参数的类型。现在,只要Element
出现在结构中,就必须使用相同的类型,但如果你想要通用类型Lock
,那么你需要声明另一个泛型类型。
这里的问题是,通过向Lock
添加另一种通用类型(即Lock<Element, AnotherElement>
),现在Lock
中的init
需要指定两种泛型类型等等。
答案 2 :(得分:0)
通过使初始化程序通用,您可能会获得更好的结果:
struct Lock<Element: Hashable> {
var element: Element
init<T>(_ element: Element, _ args:[Lock<T>]? = nil) {
self.element = element
}
}