Comment implémenter le constructeur de copie dans la sous-classe Swift?
J'ai l'exemple suivant, dans une Swift aire de jeux, dans une tentative de mettre en œuvre un constructeur de copie rapide:
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}
Le problème, c'est que ce n'est pas réellement de la compilation dans sa forme actuelle. Sur le init(copyFrom: Square)
méthode dans le Square
sous-classe, cette erreur est signalée:
Overriding method with selector 'initWithCopyFrom:' has incompatible type '(Square) -> Square'
Cette question aurait du sens si ce n'était pas un constructeurcomme s'il s'agissait d'une func
vous pourriez potentiellement passer dans un type qui est prévu dans la super-classe, mais qui a été remplacée dans la sous-classe pour être plus restrictif:
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.
Mais le fait que c'est un constructeur m'amène à croire que je devrais être en mesure de remplacer et d'en fournir une autre signature de la méthode, car il est absolument connu au moment de la compilation que le type de l'objet.
Ce problème disparaît si je modifier Shape
de ne plus étendre NSObject
. Toutefois, en raison de l'inclusion avec un code Objective-C, il doit étendre NSObject
.
Comment puis-je mettre à jour mon constructeur de copie pour permettre une Shape
de savoir c'est de la copie à partir d'un Shape
et de permettre une Square
de savoir c'est de la copie à partir d'un Square
?
source d'informationauteur Craig Otis
Vous devez vous connecter pour publier un commentaire.
init(copyFrom: Square)
est une surcharge, pas un remplacement, deinit(copyFrom: Shape)
. Ce que je veux dire, c'est qu'ils sont sans rapport avec les méthodes parce qu'ils acceptent différents types. Dans Swift qui est acceptable. En ObjC, c'est illégal. Il n'y a pas de surcharges en ObjC.Swift initialiseurs de ne pas héritent automatiquement. Donc, en Rapide, vous ne pouviez pas essayer de copier un hasard
Shape
comme unSquare
. L'initialiseur n'est pas disponible. Mais en ObjC, initialiseurs ne héritent automatiquement (et vous ne pouvez pas arrêter de le faire). Donc, si vous avez une méthodeinitWithCopyFrom:(*Shape)
il est nécessaire que chaque sous-classe, être prêt à l'accepter. Cela signifie que vous pouvez (en ObjC) essayez de créer une copie d'un Cercle dans un Carré. C'est bien sûr absurde.Si c'est un
NSObject
sous-classe, vous devez utiliserNSCopying
. Voici la façon dont vous aller à ce sujet:Swift 3
La façon la plus simple serait tout simplement de changer le nom de la sous-classe initialiser à
init(copyFromSquare: Square)
laissantSquare
avec leinit(copyFrom: Shape)
méthode intact (comme vous avez contracté en héritant deShape
).Vous pouvez bien sûr remplacer
init(copyFrom: Shape)
et de tester sicopyFrom
est unSquare
dans ce cas, vous prenez un cours de l'action (réglage de la longueur), pas autrement.Notez également que vous devez définir
self.length
avant vous appelez la super.