2016-03-16 81 views
2

我想創建一個可以採用可選參數的泛型函數。 這是我到目前爲止有:Swift - 以可選參數的泛型函數的參數爲​​零

func somethingGeneric<T>(input: T?) { 
    if (input != nil) { 
     print(input!); 
    } 
} 

somethingGeneric("Hello, World!") // Hello, World! 
somethingGeneric(nil) // Errors! 

它能與String如圖所示,但不與nil。 使用它與nil提供了以下兩個錯誤:

error: cannot invoke 'somethingGeneric' with an argument list of type '(_?)' 
note: expected an argument list of type '(T?)' 

我在做什麼錯了,我應該如何正確申報/使用這個功能嗎?此外,我想保持功能的使用盡可能簡單(我不想做類似nil as String?的東西)。

回答

0

我想通了:

func somethingGeneric<T>(input: T?) { 
    if (input != nil) { 
     print(input!); 
    } 
} 

func somethingGeneric(input: NilLiteralConvertible?) {} 


somethingGeneric("Hello, World!") // Hello, World! 
somethingGeneric(nil) // *nothing printed* 
somethingGeneric(nil as String?) // *nothing printed* 
+0

你的'somethingGeneric (輸入:T?)'func仍然不接受nil作爲一個值,但它只是通過空函數並且isn'因爲這個函數沒有做任何事情,所以如果你用nil調用func,它會通過函數'input:NilLiteralConvertible'作爲參數,但是如果你用一個nil可選來調用它,比如就像說x:String?一樣,它會通過'input:T?'作爲參數來處理func你將不得不復制你的無處理邏輯。 –

+0

@WillM。 'somethingGeneric (input:T?)'不需要'nil'; 'somethingGeneric(input:NilLiteralConvertible?)'。我選擇這種方式,因爲它適用於所有三種,但你是對的,我可以轉換'somethingGeneric (input:T?)'不採取可選,但它會打破'零作爲字符串?'(我只是沒有並不希望它是這樣調用函數的要求)。 – Coder256

+1

請注意 - 例如 - 'let ptr:UnsafePointer ? = ...; somethingGeneric(ptr)會調用* second *函數,因爲UnsafePointer是NilLiteralConvertible而第二個泛型函數更具體。 –

3

我猜編譯器不知道T只是從nil

下面的作品只是雖然例如罰款:

somethingGeneric(Optional<String>.None)

+0

'零爲字符串?'這是否太 –

+0

@WillM。我也提到我*不*希望這樣的行爲。 – Coder256

+0

我不認爲有辦法解決它。短也有'func somethingGenericWithNil()'並調用它,而不是:) –

1

我認爲你將永遠不會調用somethingGeneric(nil)但大多somethingGeneric(value)somethingGeneric(function())爲其編譯器有足夠的信息不會被試圖猜測類型:

func somethingGeneric<T>(input: T?) { 
    if let input = input { 
     print(input); 
    } 
} 

func neverString() -> String? { 
    return nil 
} 

let a: String? = nil 

somethingGeneric("Hello, World!") // Hello, World! 
somethingGeneric(a) // Nothing and no error 
somethingGeneric(neverString()) // Nothing and no error 

此外,我會使用if let語法而不是if(value != nil)

+0

我喜歡這個,但是我發現它也適用於'nil'。 – Coder256

1

我相信你已經通過要求能夠通過無類型nil(其實不存在;即使nil有一個類型)而使問題過於複雜。雖然答案中的方法似乎有效,但由於可選促銷,它允許創建??類型。你經常會感到幸運,那很有效,但是我看到它真的很令人沮喪,並且錯誤的功能被調用。問題是String可以隱式升級到String?,並且String?可以隱式升級到String??。當??隱含地出現時,幾乎總是出現混淆。

正如MartinR指出的那樣,您的方法對於調用哪個版本不太直觀。 UnsafePointer也是NilLiteralConvertible。因此,推斷將調用哪個函數很困難。 「棘手的推理」使其成爲令人困惑的錯誤的可能來源。

問題存在的唯一時間是通過文字nil。正如@Valentin所指出的那樣,如果你通過一個發生在的變量是nil,那就沒有問題;你不需要特殊情況。爲什麼強制呼叫者通過一個無類型nil?只是讓呼叫者傳遞任何東西。

我假設somethingGeneric在通過nil的情況下做了一些有趣的事情。如果情況並非如此;如果您顯示的代碼表示實際功能(即所有內容都包含在if (input != nil)檢查中),那麼這不是問題。只是不要撥打somethingGeneric(nil);這是一個可證實的無操作。只要刪除這行代碼即可。但我會假設有一些「其他工作。「

func somethingGeneric<T>(input: T?) { 
    somethingGeneric() // Call the base form 
    if (input != nil) { 
     print(input!); 
    } 
} 

func somethingGeneric() { 
    // Things you do either way 
} 

somethingGeneric("Hello, World!") // Hello, World! 
somethingGeneric() // Nothing 
其中OP基本上提到