簡體   English   中英

通用工廠方法和類型推斷

[英]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應該是什么。

您的調用隱式指定AB應該是什么,並指定該方法應返回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就這樣簡單地與AB無關,因此無法推斷。

例如。

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM