Reputation: 111
Let's say I have a color model:
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
}
}
In my view file, I add some view-details to my Color model. These details aren't model specific, they're view specific.
fileprivate extension Color {
fileprivate var representation: String {
return self.value!
}
}
fileprivate extension UnknownColor {
fileprivate var representation: String {
return "#000"
}
}
Now, when I use my color model in the view file, I expect my UnknownColor
s to represent themselves as "#000"
, but that's not the case when UnknownColor
is cast as a 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")
}
I want to avoid blatant type-checking for UnknownColor
, so a solution like this is not ideal:
func colorRepresentation(_ color: Color) {
if let color = color as? UnknownColor {
return "#000"
} else {
return color.value!
}
}
I want to avoid making further changes to the Color model at all costs.
There may be many implementations of the Color
protocol that want to make use of Color.representation
so changing the extension Color
to extension KnownColor
is not an option.
Is there a way that I can restructure my code so that the UnknownColor.representation
gets used when the Color
is actually an UnknownColor
?
Upvotes: 0
Views: 125
Reputation: 817
I copy and pasted your code directly into a Playground and it worked fine (color3.representation == "#000").
Are the extensions in a separate file? If so, the fileprivate
keyword is going to make them invisible to the classes.
For reference, here is the entire code I put into the 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")
Upvotes: 2