假设我有一个颜色模型:
protocol Color {
var value: String? { get }
}
class UnknownColor: Color {
let value: String? = nil
}
class KnownColor: Color {
let value: String?
init(value: String? = nil) {
self.value = value
}
}
在视图文件中,我向我的颜色模型添加了一些视图细节。 这些细节不是特定于模型的,而是特定于视图的。
fileprivate extension Color {
fileprivate var representation: String {
return self.value!
}
}
fileprivate extension UnknownColor {
fileprivate var representation: String {
return "#000"
}
}
现在,当我在视图文件中使用颜色模型时,我希望我的UnknownColor
可以将自己表示为"#000"
,但是UnknownColor
强制转换为Color
。
let color1 = KnownColor()
let color2 = KnownColor(value:"#fff")
let color3 = UnknownColor()
color1.representation // Fatal error (GOOD)
color2.representation // "#fff" (GOOD)
color3.representation // "#000" (GOOD)
if let color = color3 as? Color {
color.representation // Fatal error (BAD, expected "#000")
}
我想避免对UnknownColor
进行公然的类型检查,因此这样的解决方案并不理想:
func colorRepresentation(_ color: Color) {
if let color = color as? UnknownColor {
return "#000"
} else {
return color.value!
}
}
我想不惜一切代价避免对Color模型进行进一步的更改。
可能Color
协议的许多实现都想利用Color.representation
,因此将extension Color
更改为extension KnownColor
并不是一种选择。
有没有一种方法可以重组我的代码,以便在UnknownColor.representation
实际上是Color
时使用UnknownColor
?
答案 0 :(得分:2)
我将您的代码直接复制并粘贴到一个Playground中,它运行良好(color3.representation ==“#000”)。
扩展名是否在单独的文件中?如果是这样,fileprivate
关键字将使它们对类不可见。
作为参考,这是我放入Playground的全部代码:
protocol Color {
var value: String? { get }
}
class UnknownColor: Color {
let value: String? = nil
}
class KnownColor: Color {
let value: String?
init(value: String? = nil) {
self.value = value
}
}
fileprivate extension Color {
fileprivate var representation: String {
return self.value!
}
}
fileprivate extension UnknownColor {
fileprivate var representation: String {
return "#000"
}
}
let color1 = KnownColor()
let color2 = KnownColor(value:"#fff")
let color3 = UnknownColor()
//color1.representation // Fatal error (GOOD)
color2.representation // "#fff" (GOOD)
color3.representation // Fatal error (BAD, expected "#000")