Dans Swift, quelqu'un peut-il expliquer comment remplacer une propriété sur une superclasse avec un autre objet sous-classé de la propriété d'origine?
Prenons cet exemple simple:
class Chassis {}
class RacingChassis : Chassis {}
class Car {
let chassis = Chassis()
}
class RaceCar: Car {
override let chassis = RacingChassis() //Error here
}
Cela donne l'erreur:
Cannot override with a stored property 'chassis'
Si j'ai un châssis comme 'var' à la place, j'obtiens l'erreur:
Cannot override mutable property 'chassis' of type 'Chassis' with covariant type 'RacingChassis'
La seule chose que j'ai pu trouver dans le guide sous "Propriétés de remplacement" indique que nous devons remplacer le getter et le setter, ce qui peut fonctionner pour changer la valeur de la propriété (si c'est 'var'), mais qu'en est-il de la modification de la classe de propriété ?
strong
propriété et j'obtenais une erreur en essayant de la remplacer - mais il semble que j'ai manqué que cela se traduit par un "optionnel implicitement déballé" (chassis!
) dans Swift, doncoverride var chassis : Chassis!
corrige ça.Cela semble fonctionner
la source
let
dans laCar
classe, ce qui rend impossible la modification. Nous ne pouvons modifier lachassis
propriété que sur laRaceCar
classe.Essaye ça:
Ensuite:
Détails sur http://www.mylonly.com/14957025459875.html
la source
La solution Dash fournie fonctionne bien, sauf que la super classe doit être déclarée avec le mot-clé let plutôt que var. Voici une solution possible mais NON RECOMMANDÉE!
La solution ci-dessous compilera avec Xcode 6.2, SWIFT 1.1 (si toutes les classes sont dans des fichiers swift différents) mais doit être évitée car ELLE PEUT ENTRAÎNER DES COMPORTEMENTS INATTENDUS (INCLUANT UN CRASH, en particulier lors de l'utilisation de types non optionnels). REMARQUE: CELA NE FONCTIONNE PAS AVEC XCODE 6.3 BETA 3, SWIFT 1.2
la source
Théoriquement, vous êtes autorisé à le faire de cette façon ...
Cela fonctionne parfaitement dans un terrain de jeu Xcode.
Mais , si vous essayez ceci dans un vrai projet, une erreur du compilateur vous indique:
Je n'ai vérifié que Xcode 6.0 GM pour le moment.
Malheureusement, vous devrez attendre qu'Apple corrige ce problème.
J'ai également soumis un rapport de bogue. 18518795
la source
J'ai vu de nombreuses raisons pour lesquelles la conception d'une API utilisant des variables au lieu de fonctions est problématique et pour moi, l'utilisation de propriétés calculées ressemble à une solution de contournement. Il existe de bonnes raisons de garder vos variables d'instance encapsulées. Ici, j'ai créé un protocole Automobile auquel Car se conforme. Ce protocole a une méthode d'accesseur qui renvoie un objet Chassis. Puisque Car s'y conforme, la sous-classe RaceCar peut la remplacer et renvoyer une sous-classe Châssis différente. Cela permet à la classe Car de programmer sur une interface (Automobile) et la classe RaceCar qui connaît RacingChassis peut accéder directement à la variable _racingChassis.
Un autre exemple de la raison pour laquelle la conception d'une API à l'aide de variables se décompose est lorsque vous avez des variables dans un protocole. Si vous souhaitez décomposer toutes les fonctions de protocole en extensions, vous pouvez, sauf que les propriétés stockées ne peuvent pas être placées dans des extensions et doivent être définies dans la classe (pour que cela compile, vous devez décommenter le code dans AdaptableViewController et supprimez la variable mode de l'extension):
Le code ci-dessus aura cette erreur de compilation: «Les extensions peuvent ne pas avoir de propriétés stockées». Voici comment vous pouvez réécrire l'exemple ci-dessus afin que tout dans le protocole puisse être séparé dans l'extension en utilisant des fonctions à la place:
la source
Vous pouvez y parvenir avec l'utilisation de génériques:
Avec cette approche, vous aurez un code de sécurité de type 100% sans forcer le déballage.
Mais c'est une sorte de hack, et si vous avez besoin de redéfinir plusieurs propriétés, les déclarations de classe ressembleront à un désordre total. Soyez donc prudent avec cette approche.
la source
En fonction de la façon dont vous prévoyez d'utiliser la propriété, le moyen le plus simple de le faire est d'utiliser un type facultatif pour votre sous-classe et de remplacer la
didSet {}
méthode pour la super:Évidemment, vous devez passer un peu de temps à vérifier pour vous assurer que les classes peuvent être initialisées de cette façon, mais en définissant les propriétés sur facultatif, vous vous protégez contre les situations où la diffusion ne fonctionne plus.
la source
Vous pouvez simplement créer une autre variable de RacingChassis.
la source
chassis
et en nous permettant d'obtenir / définir notreRacingChassis
instance avec lachassis
propriété.Essaye ça:
la source
la source
Ce qui suit permet d'utiliser un seul objet dans les classes de base et dérivées. Dans la classe dérivée, utilisez la propriété d'objet dérivée.
la source
Une légère variation d'autres réponses, mais plus simples et plus sûres avec quelques avantages intéressants.
Les avantages incluent qu'il n'y a aucune restriction sur ce que le châssis doit être (var, let, facultatif, etc.), et il est facile de sous-classer RaceCar. Les sous-classes de RaceCar peuvent alors avoir leur propre valeur calculée pour le châssis (ou racingChassis).
la source
il suffit de définir une nouvelle propriété imageview avec une convention de dénomination différente comme imgview car imageView est déjà sa propre propriété et nous ne pouvons pas attribuer 2 propriétés fortes.
la source