[英]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.