[英]Recursive generic structs with different types in Swift 4
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)])
這會導致錯誤: 無法將“Int”類型的值轉換為預期的參數類型“Lock <_>”
您有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
的信息。
您的第二個選擇是使用associatedtype
創建protocol
。 使用具有2個init
的類似技巧,除了明確定義類型之外,您可以執行相同的操作:
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)])
第一個版本更清潔,但它更具限制性。 這取決於您使用哪一個,取決於您的需求。
這是不可能做到的。
原因是Element
被賦予init
用於element參數的類型。 現在,只要Element
出現在struct中,就必須使用相同的類型,但是如果你想要Lock
的泛型類型,你需要聲明另一個泛型類型。
這里的問題是,通過向Lock
添加另一個泛型類型(即Lock<Element, AnotherElement>
),現在init
的Lock
將需要指定兩個泛型類型,依此類推。
通過使初始化程序通用,您可能會獲得更好的結果:
struct Lock<Element: Hashable> {
var element: Element
init<T>(_ element: Element, _ args:[Lock<T>]? = nil) {
self.element = element
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.