Как я могу использовать расширение класса, чтобы переопределить расширение протокола?
Допустим, у меня есть цветовая модель:
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
}
}
В моем файле вида я добавляю некоторые детали вида в мою модель Color. Эти детали не зависят от модели, они относятся к конкретному виду.
fileprivate extension Color {
fileprivate var representation: String {
return self.value!
}
}
fileprivate extension UnknownColor {
fileprivate var representation: String {
return "#000"
}
}
Теперь, когда я использую свою цветовую модель в файле вида, я ожидаю, что мой UnknownColor
s представлять себя как "#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
?
1 ответ
Я скопировал и вставил ваш код прямо на игровую площадку, и он работал нормально (color3.representation == "#000").
Находятся ли расширения в отдельном файле? Если так, то fileprivate
Ключевое слово сделает их невидимыми для классов.
Для справки, вот весь код, который я поместил на игровую площадку:
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")