下面的代碼片段演示了我正在嘗試解決的問題。Swift條件一致性的解決方法(是:將約定添加到受約束的泛型類型)
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
但同樣,沒有運氣通過測試。
我還能做些什麼來將協議添加到約束泛型?
沒有[條件一致性](https://github.com) /apple/swift/blob/master/docs/GenericsManifesto.md#conditional-conformances-)在Swift(還沒有) - 你通常可以通過重載函數來解決這個問題,例如期望一個帶有函數的Printable輸入。 'List'輸入,其中'T'可以被約束到某個協議。或者你可以創建一個包裝類型來表示一個'List '實例,其中'T'符合一些協議 - 然後你可以將這個包裝符合到'Printable'。 –
Hamish
如果你可以用你的建議的例子寫一個答案,這將是非常有幫助的。謝謝。 – Laurent
我很抱歉沒有儘快回覆你。再看一下你的代碼,因爲你的'test'函數有一個'Any'輸入,並且你希望在運行時處理類型 - 重載對你沒有多大用處(如果你能夠保留靜態類型,那麼它會)。至於創建一個包裝類型,[這個問題和答案](http://stackoverflow.com/questions/33332613/is-it-possible-to-add-type-constraints-to-a-swift-protocol-conformance-擴展名)涵蓋了它很好(標記爲愚蠢?)。 – Hamish