簡體   English   中英

具有返回類型重載的Swift泛型函數調用函數

[英]Swift generic function calling function with return type overload

只是一個簡單的問題。 我有以下代碼,工作得很好:

class obA: Printable {
    var description: String { get { return "obA" } }
}

class obB: Printable {
    var description: String { get { return "obB" } }
}


func giveObject() -> obA { return obA() }
func giveObject() -> obB { return obB() }

var a: obA = giveObject()
var b: obB = giveObject()

println(a)
println(b)

正在調用giveObject的正確變體,一切都很好。 當然這只是一個簡化的案例,實際上在我的項目中有幾十個'giveObject'的重載,所有的返回類型都不同。 現在,我想制作一個通用函數來解析所有這些東西。 那么,下一步:

func giveGeneric<T>() -> T {
    return giveObject()
}

var c: obA = giveGeneric()
println(c)

這抱怨了對giveObject的模糊使用。 我可以理解錯誤的來源,但我不知道如何解決它並使用這樣的結構......

即使您為任何可能的類型實現了giveObject函數,這也無法工作。 由於T可以是任何類型,因此giveGeneric方法無法確定要調用的正確重載。

我能想到的唯一方法就是創建一個巨大的swift,其中包含你想要處理的類型數量的大小:

func giveGeneric<T>() -> T? {
    switch "\(T.self)" {
    case "\(obA.self)":
        return giveObject() as obA as? T
    case "\(obB.self)":
        return giveObject() as obB as? T
    default:
        return .None
    }
}

但我不認為即使拿着槍指向我的頭部也會使用這樣的解決方案 - 這真的很難看。

如果在所有情況下使用無參數構造函數創建實例,則可以創建協議並約束T泛型類型以實現它:

protocol Instantiable {
    init()
}

func giveGeneric<T: Instantiable>() -> T {
    return T()
}

您可以使用內置以及新類型 - 例如:

extension String : Instantiable {
    // `String` already implements `init()`, so nothing to add here
}

let s: String = giveGeneric()

或者,如果您願意,可以使協議聲明一個靜態的giveObject方法而不是一個無參數的構造函數:

protocol Instantiable {
    static func giveObject() -> Self
}

func giveGeneric<T: Instantiable>() -> T {
    return T.giveObject()
}

extension String : Instantiable {
    static func giveObject() -> String {
        return String()
    }
}

let s: String = giveGeneric()

首先只是一個注釋。

如果giveGeneric的泛型類型只是T ,那么它可以是任何東西(String,Int,...)。 那么在這種情況下, giveObject()應如何反應?

我的意思是,如果你寫:

let word : String = giveGeneric()

在內部你的泛型函數調用如下:

let result : String = giveObject() // Ambiguous use of giveObject

我的解決方案

我宣布了一個協議如下:

protocol MyObject {
    init()
}

然后我讓你的2個類符合協議

class obA: Printable, MyObject {
    var description: String { get { return "obA" } }
    required init() {}
}

class obB: Printable, MyObject {
    var description: String { get { return "obB" } }
    required init() {}
}

最后我可以寫這個

func giveGeneric<T:MyObject>() -> T {
    return T()
}

現在我可以使用它:

let a1 : obA = giveGeneric()
let b1 : obB = giveGeneric()

您決定這是您正在尋找的解決方案還是僅僅是一種解決方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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