[英]How to implement conditional conformance of a generic to a protocol in a function?
[英]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)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.