Here is my playground snippet:
class Box {
func clone() -> Box {
return Box() // <- how to return superclass here?
}
}
class VBox:Box { }
let vb = VBox()
let cBox = vb.clone() // now cBox is a Box, not a VBox
My clone
function returns a Box
class in all cases. But for the subclass I want it to return the superclass (so above it should return VBox
).
I know I could override
the clone
function inside VBox
but I wonder if there's a smarter way.
You mean subclass. Box is the superclass, which is what you're returning.
This is very similar to the following:
It's not exactly the same question, though, since you're dealing with classes rather than protocols, so we can go through that example. First, the right tool is init
, not a clone
:
class Box {
let a: String
init(_ a: String) { self.a = a }
convenience init(copy: Box) { self.init(copy.a) }
}
class VBox:Box {}
let vb = VBox("test")
let cBox = VBox(copy: vb)
You see that this works fine since VBox
adds no additional properties. But if VBox
does add additional properties, then you'll get all the right errors that require you to implement an init
.
class Box {
let a: String
init(_ a: String) { self.a = a }
convenience init(copy: Box) { self.init(copy.a) }
}
class VBox:Box {
let b: String
init(_ a: String, _ b: String) {
self.b = b
super.init(a)
}
convenience init(copy: VBox) {
self.init(copy.a, copy.b)
}
}
let vb = VBox("test", "this")
let cBox = VBox(copy: vb)
Note how this prevents you from trying to copy a Box
into a VBox
(since that would not initialize all the parameters). If you want that to work, you'd need to provide a copy(Box)
initializer. This is the nice thing about using init
. It keeps track of all the rules for you. NSCopying
would let you make that mistake and would eventually crash.