簡體   English   中英

Swift中條件一致性的解決方法(是:將協議添加到受約束的泛型類型中)

[英]Workaround for conditional conformance in Swift (was: Adding protocol to a constrained generic types)

下面的代碼段演示了我要解決的問題。

import Foundation

protocol Printable {
    func className() -> String
}

class SomeType: Printable {
    func className() -> String {
        return "SomeType"
    }
}

class List<T> {
}

extension List where T: SomeType {
    func className() -> String {
        return "List<SomeType>"
    }
}

func test(type: Any, message: String) {
    guard type is Printable else {
        print("\(message): ERROR")
        return
    }
    print("\(message): SUCCESS")
}

let s: Any = SomeType()
test(type: s, message: "#1")

let slist1: Any = List<Any>()
test(type: slist1, message: "#2")

let slist2: Any = List<SomeType>()
test(type: slist2, message: "#3")

我怎么能得到這個:

> #1: SUCCESS  <--- as expected
> #2: ERROR    <--- it's okay
> #3: SUCCESS  <--- I am getting ERROR instead

似乎向該行添加協議可以解決問題:

extension List: Printable where T: SomeType { // COMPILE ERROR

但不幸的是,這是不允許的。

另一種方法是使用:

extension List where T: Printable { // COMPILES OK in Swift 2.3 but doesn't work. COMPILE ERROR in Swift 3.0

但是同樣,沒有運氣通過測試。

我還可以做些什么來將協議添加到受約束的泛型類型?

好吧,在您的警惕下,您要問“如果這是可打印的,那么打印成功,否則打印錯誤”,在第一個示例中,您有s,它是可以打印的SomeType。 沒關系。

之后,您將擁有類型為List<Any> slist1,該List<Any>絕對不是可打印的類型,並且會出現“錯誤”。 沒關系

接下來,您有了List<SomeType> 現在您有了一個類擴展,將T定義為SomeType,對嗎? 但是您只是將T定義為SomeType而不是實際的List,因此當您將整個List傳遞給測試函數時,您將無法通過測試,因為List<AnyTypeHere>無法打印,因為列表本身沒有沒有實現Printable。

現在的問題是,您是否希望整個列表都可打印? 如果是這樣,則只需使其符合SomeType或Printable協議即可。 除了將單個List<SomeType>元素傳遞到函數中之外,這是傳遞它的唯一方法。 您的函數邏輯是正確的,但這只是對該概念的濫用。

因此,如果您希望List<SomeType>通過該傳遞,則可以執行類似的操作

class List<T> : Printable where T:SomeType {
  //Add code here that conforms to protocol
}

這樣做將使您的第二次測試失敗,因為Any不會從SomeType繼承,但是它將使您的第三次測試通過,因為現在List<T>是Printable且T的類型也是SomeType。 我的意思是,這只是一種獲取所需外觀的快速方法。 除非您添加其他內容,否則您將不會同時通過第二個和第三個測試,因為第二個測試是List的類型為Any,而第三個測試的List的類型為Printable。 因此,其中之一將引發錯誤(因為List的類型不是Printable)或所有測試都顯示成功(因為List的類型是Printable)

現在有了Swift 4.2,這是一個更新的答案,現在將條件一致性添加為功能。

從他們在Github上規范來看,這種代碼現在有效

   extension List : Printable where T: SomeType {
       func className() -> String {
           return "List<SomeType>"
       }
   }

暫無
暫無

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

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