[英]Generic factory method and type inference
我有以下帶有通用工廠方法的 class:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
}
extension Something {
class func zip<A, B>(_ a: A, _ b: B) -> Something<(A, B)> {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
為什么我不能在沒有明確指定返回類型的情況下調用zip
?
// ERROR: Cannot invoke `zip` with an argument list of type `(Int, Int)`
let y = Something.zip(1, 2)
// OK: Works but it’s unacceptable to require this on caller's side
let x = Something<(Int, Int)>.zip(1, 2)
感謝您的時間!
你看到這個的原因是這個電話中沒有任何內容:
let y = Something.zip(1, 2)
這告訴Swift T
應該是什么。
您的調用隱式指定A
和B
應該是什么,並指定該方法應返回Something<A, B>
。 但那個Something<A, B>
沒有連接到Something<T>
。
事實上,你的電話中沒有任何東西與T
; T
未指定,因此可能是任何東西。 我的意思是字面意思 - 你實際上可以在Something
之后將(幾乎)任意隨機類型放在尖括號中並且它將完全相同:
let y = Something<UICollectionViewDelegateFlowLayout>.zip(1, 2)
你真正想做的是以某種方式指定T
必須是一個元組,並且這兩個參數與元組的元素具有相同的類型。 不幸的是,Swift目前還沒有正確執行此操作所需的功能。 如果語言更復雜,你可以這樣說:
extension<A, B> Something where T == (A, B) {
class func zip(a: A, _ b: B) -> Something {
let initial = (a, b)
return Something(initial: initial)
}
}
但是現在,你將不得不處理這個可怕的黑客攻擊,它通過毫無意義地重用T
類型參數來工作,這樣它就不再處於松散狀態:
extension Something {
class func zip<B>(a: T, _ b: B) -> Something<(T, B)> {
let initial = (a, b)
return Something<(T, B)>(initial: initial)
}
}
簡而言之,您使用泛型不正確。 它不是實時功能,它是預編譯的東西。 如果需要從泛型輸入值中創建抽象類,請查看並執行以下操作:
class Abstract<T> {
init(value: T) {
print("inputed value: \(value)")
}
}
class Something {
class func zip<A, B>(value: A, value2: B) -> Abstract<(A, B)> {
print("Something.zip", value, value2)
return Abstract<(A, B)>(value: (value, value2))
}
}
Something.zip(5, value2: 40) // "inputed value: (5, 40)"
T
就這樣簡單地與A
和B
無關,因此無法推斷。
例如。
let z = Something<(String, String)>.zip(1, 2)
let z2 = Something<AnyObject>.zip(1, 2)
工作得很好,可以返回Something<(Int, Int)>
您可以像這樣為您的案例引入類型推斷:
final class Something<T> {
let value: T
init(initial: T) {
value = initial
}
class func zip<A, B>(_ a: A, _ b: B) -> Something<T> where T == (A, B) {
let initial = (a, b)
return Something<(A, B)>(initial: initial)
}
}
let y = Something.zip(1, 2) //works
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.