[英]Downcast protocol conformance in extension
假設我有兩個非基因協議(1)
protocol StringValue {
var asString: String {get}
}
protocol StringProvider {
var value: StringValue {get}
}
我想擁有第二個的通用版本(2)
protocol TypedStringProvider: StringProvider { // inherits from StringProvider
associatedtype TypedStringValue: StringValue
var typedValue: TypedStringValue { get }
}
並且使用非泛型版本的默認實現擴展,以使代碼免費符合StringProvider
( 不起作用 ,請參閱下文) (3)
extension TypedStringProvider {
var value: TypedStringValue { return typedValue }
}
現在我想要幾個類來兼容泛型TypedStringProvider
和非泛型StringProvider
協議(4)
extension UIView: TypedStringProvider {
typealias TypedStringValue = String
var typedValue: String { return "Some String" }
}
extension Double: TypedStringProvider {
typealias TypedStringValue = String
var typedValue: String { return String(self) }
}
extension String: StringValue {
var asString: String { return self }
}
並得到編譯器錯誤: Type 'UIView' does not conform to protocol 'StringProvider'
。
貌似擴展(3)不能像我想的那樣工作,因為TypedStringValue
不是StringValue
,盡管有這種約束associatedtype TypedStringValue: StringValue
from(2)
問題是如何在保持value
類型的同時符合非泛型StringProvider
示例 :
0.5.value.lowercased()
當然StringValue
沒有來自String
lowercased
方法,所以它不會編譯。
我嘗試過的:
首先是向擴展名添加無類型屬性(3)
extension TypedStringProvider {
var value: TypedStringValue { return typedValue }
var value: StringValue { return typedValue }
}
由於Invalid redeclaration of 'value'
錯誤的Invalid redeclaration of 'value'
因此無法正常工作
第二是擴展我的類並在那里添加無類型屬性(5)
extension UIView {
var value: StringValue { return typedValue }
}
extension Double {
var value: StringValue { return typedValue }
}
它工作沒有編譯器錯誤, 但
在我們的示例中沒有針對lowercased
自動完成。
使用擴展(5)我需要為符合StringProvider
每個類和此協議具有的每個屬性編寫大量代碼
有任何想法嗎?
value
定義為StringValue
類型,因此這是您應在TypedStringProvider
擴展中指定的類型,以便完成協議一致性:
extension TypedStringProvider {
var value: StringValue {
return typedValue
}
}
找到解決方案
extension StringProvider where Self: TypedStringProvider {
var value: StringValue { return typedValue }
}
使用此擴展,不需要為每個類編寫類似的擴展,自動完成也可以。
完整代碼:
protocol StringValue {
var asString: String {get}
}
protocol StringProvider {
var value: StringValue {get}
}
protocol TypedStringProvider: StringProvider {
associatedtype TypedStringValue: StringValue
var typedValue: TypedStringValue { get }
}
extension StringProvider where Self: TypedStringProvider {
var value: StringValue { return typedValue }
}
extension TypedStringProvider {
var value: TypedStringValue { return typedValue }
}
extension UIView: TypedStringProvider {
typealias TypedStringValue = String
var typedValue: String { return "some string" }
}
extension Double: TypedStringProvider {
typealias TypedStringValue = String
var typedValue: String { return String(self) }
}
extension String: StringValue {
var asString: String { return self }
}
let doubleValue = 0.5.value.lowercased()
在StringProvider
您要為StringValue
定義value
:
protocol StringProvider {
var value: StringValue { get }
}
但是在這里你要定義TypedStringValue
的類型,它與StringValue
。 (基礎值可以是TypedStringValue
,但是在使用它時需要從StringValue
到TypedStringValue
進行類型轉換)
extension TypedStringProvider {
var value: TypedStringValue { return typedValue }
}
我現在可以為這種情況提出兩種解決方案:
如果您想使value
通用並根據TypedStringProvider
更改類型,您可以:
protocol StringProvider {
associatedtype StringProviderValue: StringValue
var value: StringProviderValue { get }
}
通過將StringProviderValue
定義為TypedStringValue
來符合協議
extension TypedStringProvider {
var value: TypedStringValue { return typedValue }
}
保持StringProvider
原樣:
protocol StringProvider {
var value: StringValue { get }
}
通過使用正確的StringValue
類型符合協議,並在其中返回typedValue: TypedStringValue
,可以下載到StringValue
extension TypedStringProvider {
var value: StringValue { return typedValue }
}
兩種解決方案都提供相同的輸出
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.