簡體   English   中英

我可以將通用參數限制為 *not* 是可選的嗎?

[英]Can I constrain a generic parameter to *not* be optional?

假設我有這個代碼:

func hello<T>(thing: T) -> String {
    return "hello \(thing)"
}

我可以編寫一個hello function 的版本,如果它通過了可選項則無法編譯?

let foo = "some"
let bar: String? = nil

print(helloNoOptional(foo))  // should compile
print(helloNoOptional(bar))  // should not compile

我在想也許它可以通過協議一致性或 T 上的where子句來實現,但我想不出它究竟是如何工作的。

我想這樣做的原因是因為我正在處理遺留代碼庫中的實際 function,如果thing為零,它就沒有明智的行為。 因此,我寧願阻止hello被調用可選,而不是處理 hello 內部的展開thing並試圖找出合理的錯誤行為。

更新:

一條可能的路徑...我意識到 Optional 枚舉符合NilLiteralConvertible協議。 因此,如果我能找到一種方法來限制我的泛型符合類型,我可以排除事實上的選項。 但我不知道是否有可能做類似的事情

<T where !T: NilLiteralConvertible>

我能想到的最好是在運行時重載和檢查:

func hello<T>(thing: T) -> String {
    return "hello \(thing)"
}

fun hello<T>(thing: T?) -> String {
    fatalError("No optionals allowed!")
}

hello("swift")  // fine
hello(2)        // fine
hello(Int("2")) // fatal error

但我不知道一種生成編譯時錯誤的方法。

編輯

您可以創建一個虛擬協議(下面的NotOfOptionalType ),並通過此協議擴展您希望在通用函數中使用的所有類型。 最后使用偽協議作為泛型函數中參數的類型約束; optionals不符合此類型約束,如果將它們作為這些函數的參數發送,則會在編譯時給出錯誤。

// dummy protocol
protocol NotOfOptionalType {}

extension String : NotOfOptionalType {}
extension Int : NotOfOptionalType {}
extension Double : NotOfOptionalType {}
// ... extend to the types you will use

func hello<T: NotOfOptionalType > (thing: T) -> String {
    return "hello \(thing)"
}

let foo = "some"
var bar: String? = nil

print(hello(foo))  // compiles
print(hello(bar))  // fails at compile time
bar = "something"
print(hello(bar))  // fails at compile time
print(hello(bar!)) // compiles

基於@Airspeed Velocity 的回答,我個人更喜歡將所有東西都放在一個地方,就像這樣......

func hello<T>(_ thing: T) -> String {
    
    if T.self is ExpressibleByNilLiteral.Type {
        fatalError("Optional types not supported")
    }

    return "hello \(thing)"
}

暫無
暫無

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

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