I have the following example in a Swift playground, in an attempt to implement a copy constructor in Swift:
class Shape : NSObject {
var color : String
override init() {
color = "Red"
}
init(copyFrom: Shape) {
color = copyFrom.color
}
}
class Square : Shape {
var length : Double
override init() {
super.init()
length = 10.0
}
init(copyFrom: Square) { /* Compilation error here! */
super.init(copyFrom: copyFrom)
length = copyFrom.length
}
}
let s : Square = Square() // {{color "Red"} length 10.0}
let copy = Square(copyFrom: s) // {{color "Red"} length 10.0}
s.color = "Blue" // {{color "Blue"} length 10.0}
s // {{color "Blue"} length 10.0}
copy // {{color "Red"} length 10.0}
The problem is that this doesn't actually compile in its current form. On the init(copyFrom: Square)
method in the Square
subclass, this error is reported:
Overriding method with selector 'initWithCopyFrom:' has incompatible type '(Square) -> Square'
This issue would make sense if it wasn't a constructor, as if it were a regular func
, you could potentially pass in a type that is expected in the superclass, but that has been overridden in the subclass to be more restrictive:
let mySquare : Shape = Square() // Note the var is a SHAPE
mySquare.someShapeMethod("Test") // If Square overrides someShapeMethod() to expect Int, compiler errors out to protect us here.
But the fact that it's a constructor leads me to believe that I should be able to override it and provide a different method signature, since it's absolutely known at compile time what the type of the object is.
This issue disappears if I alter Shape
to no longer extend NSObject
. However, due to inclusion with an existing Objective-C code, it needs to extend NSObject
.
How can I update my copy constructor to allow a Shape
to know it's copying from a Shape
, and allow a Square
to know it's copying from a Square
?