Programmation rapide 101 : Héritage et polymorphisme

Dans des articles précédents, j'ai abordé la question de l'héritage dans Swift. Dans ce billet, je vais approfondir la question et vous donner une image plus complète du fonctionnement de l'héritage dans Swift, et de la façon dont vous pouvez l'utiliser pour créer des applications faciles à étendre lorsque vous avez besoin d'ajouter de nouvelles fonctionnalités. En cours de route, vous découvrirez également l'important concept de polymorphisme et apprendrez à utiliser les nouveaux terrains de jeu de Xcode !

Maîtrisez votre iPhone en une minute par jour :

Inscrivez-vous à la newsletter "Tip of the Day" de iphonologie et nous vous enverrons chaque jour un conseil pour gagner du temps et tirer le meilleur parti de votre iPhone ou iPad.

L'héritage vous permet de créer de nouvelles classes basées sur d'autres classes. Par exemple, La figure 1 montre une classe Calculatrice scientifique sous-classée d'une classe Calculatrice . Dans cette relation, Calculatrice est la superclasse et Calculatrice scientifique est la sous-classe .

Figure 1 - La calculatrice scientifique est une sous-classe de la calculatrice .

La spécification d'une superclasse est facultative, mais vous pouvez en spécifier une dans la déclaration de classe :

Une classe sans superclasse est appelée classe de base .

La beauté de l'héritage est qu'il n'est pas nécessaire de créer toutes les classes à partir de zéro. Vous pouvez créer une sous-classe à partir d'une classe existante, hériter de toutes ses propriétés et méthodes et l'étendre pour répondre à vos besoins.

Dans cet exemple, la Calculatrice scientifique hérite de toutes les fonctionnalités de sa Calculatrice superclasse, y compris ajouter , soustraire , multiplier , diviser , et effacer méthodes. Vous ne devez pas réécrire ces méthodes pour la classe ScientificCalculator . Elles sont simplement héritées. Vous pouvez ajouter des méthodes à la classe ScientificCalculator - telles que log , sin , cos , et tan - qui étendent ses fonctionnalités et le spécialisent.

Méthodes dérogatoires

Parfois, vous pouvez avoir besoin de passer outre une méthode ou un bien hérité d'une superclasse. Pour remplacer un membre hérité, il faut déclarer une nouvelle implémentation de ce membre dans un fichier de classe et la marquer avec le mot-clé override .

Le fait d'outrepasser un membre hérité vous permet de le faire :

  • Étendre le membre en faisant quelque chose de plus dans la sous-classe
  • Annulez le membre de la superclasse en faisant quelque chose de complètement différent dans la sous-classe.

Pour accéder à un membre de superclasse comme une propriété ou une méthode, utilisez le super . suivi du nom du membre que vous remplacez.

Voyons un exemple d'héritage. Pour suivre, téléchargez l'exemple de projet à partir de ce lien .

  1. Ouvrez le projet AdvancedSwiftDemo que vous venez de télécharger.
  1. Dans le navigateur de projet, vous pouvez descendre dans le nœud AdvancedSwiftDemo pour voir les classes Calculator et ScientificCalculator .
  1. Sélectionnez le fichier de code Calculator.swift dans le navigateur de projet et prenez note de la méthode clear dans la superclasse Calculator :

  1. Sélectionnez le fichier ScientificCalculator.swift pour voir qu'il s'agit d'une sous-classe de la classe Calculator :

  1. Notez qu'il existe également une méthode claire qui est héritée de la classe Calculatrice :

Cette méthode a priorité sur la méthode clear de la superclasse Calculator . Rappelez-vous que vous surchargez une méthode héritée en ajoutant une méthode avec la même signature dans la sous-classe et en la marquant avec le mot-clé override , comme indiqué ci-dessus.

Dans la première ligne de code se trouve un appel à super.clear , qui appelle la méthode clear de la superclasse Calculator . Cette méthode est très courante. Lorsque vous outrepassez une méthode, vous appelez souvent la méthode de la superclasse en plus du code personnalisé que vous avez ajouté. Cela vous permet d'étendre les fonctionnalités existantes de la méthode, car vous exécutez toujours la méthode dans la superclasse et vous faites quelque chose de plus dans la sous-classe.

Lorsque la méthode est exécutée dans la sous-classe :

  • Tout d'abord, un appel est fait à la méthode de la superclasse Calculator clear qui efface la propriété total .
  • L'exécution se déplace vers la sous-classe ScientificCalculator clear method et la propriété memory est effacée.

Pour voir cela au moment de la course :

  1. Développez le nœud AdvancedSwiftDemoTests dans le navigateur de projet, puis sélectionnez le fichier de code AdvancedSwiftDemoTests.swift .
  1. Ajoutez la méthode de test suivante avant la fermeture du corset de la classe :

Bien qu'il ne s'agisse pas d'un véritable test unitaire, ce code crée une instance de la classe ScientificCalculator et appelle ensuite la méthode clear de l'objet afin que nous puissions voir comment cela fonctionne au moment de l'exécution.

  1. Ensuite, fixez un point de rupture sur la première ligne de code de la nouvelle méthode de test en cliquant dans la gouttière à gauche ( Figure 2 ).

Figure 2 - Fixer un point de rupture.

  1. Appuyez sur Command+B pour construire le projet.
  1. Dans la barre d'outils du navigateur sur le côté gauche de la fenêtre Xcode, cliquez sur le cinquième bouton à partir de la gauche pour sélectionner le navigateur de test, puis cliquez sur le bouton d'exécution à droite de la méthode de test testScientificCalculatorClear ( Figure 3 ). Note : Si vous ne voyez pas ce test, cliquez simplement sur le bouton "Exécuter" à droite du dossier "AdvancedSwiftDemo tests".

Figure 3 - Exécution du test TestScientificCalculatorClear

  1. Cela vous fait atteindre le point de rupture dans la méthode de test ( Figure 4 ). Comme vous pouvez le voir, le code qui crée une instance de la classe ScientificCalculator est en attente d'exécution.

Figure 4 - Le point de rupture est atteint.

  1. Dans la barre d'outils Debug en bas de la fenêtre Xcode, cliquez sur le bouton Step into pour exécuter cette ligne de code. Cela lance le processus de création de l'objet et vous amène à l'initialisation de la propriété de la mémoire de ScientificCalculator ( Figure 5 ).

Figure 5 - Initialisation de la propriété mémoire

  1. Appuyez à nouveau sur le bouton Step into . Cela vous amène à l'initialisation de la propriété Total de la classe de la calculatrice ( Figure 6 ).

Figure 6 - Initialisation de la propriété totale

  1. Cliquez sur le bouton Step out et vous serez renvoyé à la première ligne de la méthode de test. Appuyez sur le bouton Step over et l'objet ScientificCalculator initialisé qui est renvoyé en appelant ScientificCalculator() est stocké dans la variable calc ( Figure 7 ).

Figure 7 - L'objet ScientificCalculator est créé.

  1. Avec un objet ScientificCalculator entièrement initialisé, vous êtes prêt à exécuter sa méthode clear . Cliquez sur le bouton Step into et vous serez amené à la première ligne de code de la méthode clear de l'objet ScientificCalculator ( Figure 8 ).

Figure 8 - Exécution de la méthode de l'objet de ScientificCalculator clear .

  1. Le code qui appelle la méthode superclass clear est en attente d'exécution. Cliquez sur le bouton Step into et l'exécution se poursuit avec la méthode clear de la calculatrice, qui se prépare à stocker 0.0 dans sa propriété total ( Figure 9 ).

Figure 9 - Exécution de la méthode de la calculatrice claire

  1. Cliquez sur le bouton Step out et vous serez ramené à la méthode clear de l'objet ScientificCalculator , qui attend pour exécuter la ligne de code qui stocke 0.0 dans la mémoire propriété ( Figure 10 ).

Figure 10 - Préparation de l'effacement de la propriété de la mémoire .

  1. Cliquez sur Step out et ensuite sur Step over , et l'exécution se déplacera vers la fin de la méthode de test ( Figure 11 ).

Figure 11 - Retour à la méthode de test

  1. Cliquez sur le bouton Continue dans la barre d'outils Debug pour terminer le test.

Quelques notes supplémentaires sur la surcharge - lorsque vous surchargez une méthode, vous pouvez choisir d'ajouter un code personnalisé avant l'appel au super , ou après l'appel au super (ou les deux). Par exemple :

De plus, si vous éliminez l'appel à la méthode superclass, vous surchargez complètement le code dans la superclass, car ce code ne s'exécute jamais. Il est plus courant de étendre une méthode en incluant l'appel à super .

Propriétés prépondérantes

Bien qu'il soit plus courant d'outrepasser les méthodes, il peut arriver que vous souhaitiez outrepasser les propriétés d'une superclasse pour ajouter de nouvelles fonctionnalités à la sous-classe. Examinons les instructions étape par étape pour voir comment procéder.

  1. Commencez par créer un nouveau terrain de jeu. Sélectionnez File> New> Playground... dans le menu de Xcode.
  1. Dans la boîte de dialogue Créer un terrain de jeu, changez le nom en InheritancePlayground . Assurez-vous que la plate-forme est réglée sur iOS , puis cliquez sur Suivant .
  1. Dans la boîte de dialogue Enregistrer, sélectionnez un dossier pour enregistrer la cour de récréation et cliquez ensuite sur Créer
  1. Supprimez l'exemple de code "Hello playground" en haut de la cour de récréation.
  1. Ajoutez le code suivant à l'aire de jeu qui déclare une classe PatientEntity avec trois propriétés :

Cette classe PatientEntity contient un numéro de sécurité sociale, qui est une information sensible. Ajoutez le code suivant dans la cour de récréation sous la déclaration de classe :

Ce code crée une instance de la classe PatientEntity et accède ensuite à sa propriété SSN . Cela permet d'afficher les informations de la Figure 12 dans la barre latérale des résultats.

Figure 12 - Le PatientEntity numéro de sécurité sociale

Dans la plupart des cas, les personnes qui consultent les informations relatives à ce patient ne devraient pas pouvoir voir leur numéro de sécurité sociale complet. Créons donc une sous-classe plus sûre.

  1. Ajoutez le code suivant dans la cour de récréation en dessous du code que vous venez d'ajouter :

PatientSecureEntity est une sous-classe de PatientEntity et prévaut sur la propriété héritée SSN . Quelques points importants à noter à propos de ce code :

  • Pour outrepasser une propriété, vous devez utiliser le mot-clé override et ensuite vous devez spécifier à la fois le nom et le type de la propriété. Cela permet au compilateur de vérifier que vous écrasez la bonne propriété.
  • Dans la superclasse PatientEntity , la propriété SSN est une propriété stockée. Dans Swift, vous pouvez remplacer n'importe quelle propriété, qu'elle soit stockée ou calculée.
  • Le code de la méthode get se déclenche à chaque fois que la propriété SSN est accédée. Ce code renvoie une série d'astérisques et de tirets suivis des quatre derniers chiffres du numéro de sécurité sociale.
  • Dans la méthode get , vous pouvez accéder à la valeur de la propriété en utilisant la syntaxe super.propertyName .
  • Si la superclasse déclare une propriété en lecture-écriture, vous devez fournir les méthodes get et set dans la sous-classe. Cependant, si la superclasse déclare une propriété en lecture seule, vous pouvez la faire lire-écrire dans la sous-classe.
  • Si vous déclarez une méthode set dans une sous-classe, vous devez également déclarer une méthode get . Si vous ne voulez rien faire dans la méthode get , il suffit de retourner super.propertyName .
  • Le code de la méthode set est déclenché lorsqu'une valeur est stockée dans la propriété. Comme le montre l'exemple de code, vous pouvez accéder à la valeur enregistrée dans la propriété en utilisant l'argument newValue .
  1. Ajoutez maintenant le code suivant sous le PatientSecureEntity pour tester la surcharge de propriété :

Ce code crée une instance de PatientSecureEntity et accède ensuite à sa propriété SSN . Cela permet d'afficher les informations de la figure 15 dans la barre latérale des résultats.

Figure 13 - Le PatientSecureEntity SSN

Bien que la première ligne de la barre latérale des résultats indique l'état interne de la propriété SSN , toute personne faisant référence à la propriété SSN dans le code ne verra que les quatre derniers chiffres comme indiqué à la deuxième ligne.

  1. Vous pouvez effectivement créer une propriété en lecture seule en n'ajoutant aucun code à la méthode set . Comme il s'agit de la version sécurisée de l'entité, vous ne voudrez peut-être pas autoriser la modification du numéro de sécurité sociale du patient. Commentez le code dans la méthode set comme indiqué ici :

  1. Voyons maintenant ce qui se passe si nous essayons d'attribuer une valeur à la propriété PatientSecureEntity de l'objet SSN . Ajoutez le code suivant sous le code que vous avez ajouté à l'étape précédente :

Consultez la barre latérale des résultats et vous verrez que la valeur de la propriété SSN n'a pas changé !

Prévenir les abus

Parfois, vous pouvez vouloir empêcher quelqu'un de passer outre un membre d'une classe ou une classe entière. Pour ce faire, utilisez le modificateur final .

Par exemple, si vous ne voulez pas que quelqu'un passe outre la propriété SSN de la classe PatientSecureEntity , vous pouvez la marquer avec le modificateur final comme ceci :

Vous pouvez éviter que toute la classe ne soit écrasée en la marquant comme final :

Et voici une méthode marquée comme définitive :

Polymorphisme

Le polymorphisme est l'un des principes fondamentaux de la programmation orientée objet, et il faut vraiment bien le comprendre pour écrire le code le plus efficace.

Jusqu'à présent, chaque fois que vous avez déclaré une variable d'un type particulier, vous avez toujours stocké un objet de ce même type dans la variable. Par exemple, le code suivant déclare une variable de type UITextField , puis crée une instance de UITextField et la stocke dans la variable textField :

Pas de surprises ici. Cependant, dans Swift, lorsque vous déclarez une variable d'un type particulier, elle peut également contenir une référence à n'importe quelle sous-classe de ce type. Par exemple, prenez la hiérarchie des classes illustrée dans la figure 14 , qui montre UITextField , UIButton , et UISlider , juste quelques unes des sous-classes de la classe UIControl .

Figure 15 - Lorsque vous déclarez une variable d'un type particulier, elle peut contenir une référence à n'importe quelle sous-classe de ce type.

Le mot "polymorphisme" signifie "de nombreuses formes", et dans cet exemple vous pouvez voir que la classe UIControl peut prendre de nombreuses formes différentes - un champ de texte, un bouton ou un interrupteur.

Compte tenu de cette hiérarchie, vous pouvez déclarer une variable de type UIControl et ensuite enregistrer une référence à l'objet UITextField , UIButton ou UISwitch dans cette variable :

Le polymorphisme vous permet d'écrire un code plus générique qui fonctionne avec des familles d'objets, plutôt que d'écrire un code pour une classe spécifique. Dans cet exemple, quelle que soit la classe que vous instanciez, vous pouvez accéder à toutes les propriétés et méthodes déclarées dans la classe UIControl qui sont héritées par toutes les sous-classes.

Par exemple, la classe UIControl a une propriété activée , vous pouvez donc écrire la ligne de code suivante :

La classe UIControl possède également une méthode isFirstResponder , de sorte que vous pouvez appeler la méthode suivante sur l'objet de contrôle :

Conclusion

Au fil du temps, à mesure que vous écrirez d'autres applications iOS, vous trouverez de nombreuses utilisations de l'héritage et du polymorphisme dans la construction de bibliothèques de code et de classes généralisées qui peuvent être réutilisées dans de nombreuses applications différentes. Vous devrez également apporter de nombreuses modifications à votre application pendant sa durée de vie, il est donc important d'utiliser ces outils pour rendre vos applications flexibles et extensibles !

Click to rate this post!
[Total: 0 Average: 0]

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *