Analyse et test du code
Utilisation correcte des types de données et des conversions de types
Traitement des zones de caractères
Utilisation du Pushdown de code dans ABAP SQL
Amélioration de la performance des tables internes
Implémentation des contrôles des autorisations
Conception d'un code orienté objet efficace
Définition et utilisation des classes d'exception
Ajout de documentation au code ABAP

Implémentation de l'héritage

Objective

After completing this lesson, you will be able to implémenter une classe spécialisée.

Implémentation de l'héritage

Visionnez cette vidéo pour comprendre le concept de cours généraux et plus spécialisés.

Héritage - La relation "Est A"

Dans la modélisation, on parle de spécialisation. L'implémentation de cette relation dans un langage de programmation utilise le concept d'héritage, dans lequel une nouvelle classe (la sous-classe) est dérivée d'une classe existante (la surclasse). Un test fiable pour voir s'il existe une véritable relation d'héritage entre deux classes est d'essayer de dire "une sous-classe est une surclasse". Si cela est clairement vrai, vous avez une relation de transmission de données. Si ce n'est clairement pas vrai, ou même semble un peu étrange, vous n'avez pas de relation d'héritage et ne devez pas en mettre en œuvre car cela causera probablement des problèmes plus loin dans la ligne. Lors de l'essai de notre modèle, nous pouvons certainement dire qu'"un avion cargo est un avion" et "un avion de passagers est un avion".

Une classe qui hérite d'une surclasse contient automatiquement tous les membres de la surclasse. Ainsi, par exemple, la classe avion de transport de passagers a un constructeur et un type comme le fait un avion. Cela ne devrait pas être surprenant, car un avion de passagers est un avion. Ce qui peut d'abord apparaître supranéité, c'est que la classe d'avion de passagers ne peut pas accéder à son propre constructeur et type. En effet, il s'agit d'attributs privés de la surclasse et, en tant que tels, ils ne sont pas accessibles à la sous-classe. Plus tard, vous apprendrez une façon de permettre à une sous-classe d'accéder aux composants d'une surclasse sans les rendre entièrement publics.

Définition de la relation de transmission de données

Dans ABAP, vous implémentez l'héritage à l'aide de l'option INHERITING FROM dans l'instruction de définition de classe. Dans cet exemple, la classe avion passager est définie comme une sous-classe de la classe plane. Notez que la sous-classe connaît sa surclasse, mais la classe avion n'a aucune idée de ses sous-classes (le cas échéant).

Une sous-classe ne peut avoir qu'une seule surclasse directe.

Une surclasse - N'importe quel nombre de sous-classes

La classe plane peut avoir n'importe quel nombre de sous-classes, mais elle n'en connaît aucune.

Chaque sous-classe a une seule superclasse directe. Il connaît sa superclasse, mais ne connaît aucune classe frère (d'autres classes qui sont dérivées de la même surclasse). Dans notre exemple, la classe d'avion de passagers n'a aucune connaissance de la classe d'avion de fret.

Extension d'une sous-classe

Une fois que vous avez déclaré une sous-classe, vous devez y ajouter de nouveaux composants ou modifier les composants existants. C'est ce qui transforme la simple copie de la classe d'avion en avion de passagers ou en avion cargo. Grâce à l'héritage, vous n'avez pas besoin d'implémenter la classe à partir de zéro, vous l'étendez simplement aux nouveaux composants dont elle a besoin.

Il existe trois façons de procéder :

Ajouter de nouveaux composants : vous pouvez déclarer de nouveaux attributs, types, constantes et méthodes dans la classe. Leurs noms ne doivent pas entrer en conflit avec d'autres noms qui ont déjà été utilisés pour déclarer des membres dans la surclasse. Vous devez également vous assurer que les nouveaux composants sont pertinents uniquement pour la sous-classe et non pour toutes les spécialisations de la surclasse. Si vous déclarez un nouvel attribut ou une nouvelle méthode qui est généralement pertinent(e), vous devez le/la déplacer dans la surclasse.

Redéfinir les méthodes : lorsque vous appelez une méthode héritée, le système d'exécution exécute l'implémentation de la méthode à partir de la surclasse. Cependant, cette implémentation ne peut pas prendre en compte les nouveaux composants que vous avez déclarés dans la sous-classe. Dans ce cas, vous pouvez redéfinir la méthode. Cela signifie que vous pouvez lui affecter une nouvelle implémentation pertinente pour la sous-classe.

Ajouter un nouveau constructeur : Les constructeurs s'assurent que les nouvelles instances de la classe sont correctement initialisées. Lorsque vous créez une instance d'une sous-classe, le système d'exécution exécute toujours le constructeur de la surclasse. Ceci garantit, par example, qu'un avion de tourisme a un constructeur et un type de la même manière que n'importe quel autre avion. Cependant, le constructeur de la surclasse ne peut pas initialiser les attributs de la sous-classe, car il ne sait pas qu'ils existent. Pour cette raison, vous pouvez définir un nouveau constructeur pour la sous-classe.

Déclarer de nouveaux composants

Vous pouvez étendre une sous-classe en déclarant de nouveaux composants. Celles-ci sont visibles pour la classe elle-même mais pas pour la surclasse, et aussi pour aucune autre classe qui hérite de la même surclasse. Vous devez donc déterminer si les nouveaux composants sont pertinents uniquement dans la classe actuelle ou s'ils doivent réellement être déclarés dans la surclasse.

Composants protégés

Même si une sous-classe contient tous les attributs de sa surclasse, elle n'est pas autorisée à accéder directement aux composants privés. Parfois, cela est nécessaire, mais il y a d'autres moments où une surclasse doit laisser ses sous-classes accéder à des attributs ou méthodes particuliers sans les rendre entièrement publiques. Il peut le faire en les déclarant dans la section protégée. Les composants protégés sont visibles au sein même de la classe mais aussi pour toutes les sous-classes.

Dans la définition de classe, vous introduisez la section protégée à l'aide de l'instruction PROTECTED SECTION. Vous devez toujours déclarer les sections de visibilité dans la séquence SECTION PUBLIC - SECTION PROTÉGÉE - SECTION PRIVÉE.

Vous pouvez déplacer un composant existant d'une classe à l'aide d'un correctif rapide. Pour ce faire, placez le curseur sur le nom du composant dans ADT et appuyez sur Ctrl + 1, puis sélectionnez le correctif rapide Définir <élément> comme protégé.

Le déplacement d'un composant privé vers la section protégée est une modification compatible - vous avez élargi la visibilité du composant. Cependant, la protection d'un composant public est une modification incompatible et peut entraîner des erreurs de syntaxe. En effet, vous avez limité la visibilité du composant, qui a peut-être déjà été utilisé en dehors de la hiérarchie d'héritage.

Redéfinition des méthodes

Les surclasses contiennent souvent des méthodes que vous voulez utiliser dans une sous-classe, mais leurs implémentations ne conviennent pas car elles ne prennent pas en compte la nature particulière de la sous-classe. Par exemple, la méthode get_attributes de la classe plane ne peut pas retourner des attributs définis dans la classe avion passager. Cependant, la classe d'avion de transport de passagers a encore besoin d'une méthode get_Attributes.

Dans ABAP, vous pouvez résoudre ce problème en redéfinissant la méthode d'instance get_Attributes. Lorsque vous redéfinissez une méthode, vous écrivez une nouvelle implémentation pour celle-ci dans la sous-classe qui prend en compte les éléments que seule la sous-classe peut connaître. Cependant, la définition de la méthode reste exactement la même. Vous devez suivre ces règles :

  • La méthode conserve le même nom.
  • Vous indiquez que vous voulez redéfinir la méthode en la déclarant dans la sous-classe avec l'option REDEFINITION.
  • La méthode a la même visibilité que dans la surclasse.
  • Vous ne devez pas modifier la signature de la méthode.

Vous ne pouvez pas redéfinir une méthode statique.

Implémentation de la redéfinition

Lorsque vous implémentez la redéfinition d'une méthode, vous pouvez appeler l'implémentation dans la surclasse. Pour ce faire, utilisez la référence d'objet implicite super, qui pointe vers la surclasse dans l'instance actuelle. De cette façon, vous pouvez réutiliser l'implémentation de méthode de la surclasse, puis l'ajouter dans votre propre implémentation.

Vous n'avez pas besoin de déclarer la variable de référence super. Il est automatiquement disponible dans l'implémentation des méthodes redéfinies.

L'appel de la méthode dans la surclasse de cette manière est facultatif. Parfois ce sera une bonne idée, parfois il n'y a rien à y gagner.

Nouvelle définition de constructeur

Dans une sous-classe, vous pouvez définir un nouveau constructeur. Contrairement aux redéfinitions de méthodes, un constructeur peut avoir sa propre signature. La signature d'un constructeur contiendra souvent les mêmes paramètres que le constructeur de la superclasse, plus de nouveaux paramètres qui lui sont propres. En effet, le nouveau constructeur d'instance a deux tâches - d'abord d'appeler le constructeur de la superclasse, puis de s'occuper d'initialiser ses propres attributs qui sont spécifiques à la sous-classe.

En plus de définir un nouveau constructeur, vous pouvez également définir un nouveau constructeur statique dans une sous-classe.

Rôle du constructeur

Le constructeur d'une sous-classe a deux fonctions : il doit s'assurer que les membres de la surclasse sont correctement initialisés, et ensuite, il peut définir les valeurs initiales des attributs de la sous-classe.

Dans notre exemple, étant donné qu'un avion de transport de passagers est un avion, il ne peut y avoir d'instance d'avion de passagers que si le constructeur de la classe d'avion a réussi à régler le constructeur et le type du nouvel avion de transport de passagers. Ce n'est qu'après cela que la classe d'avion de passagers peut définir ses propres attributs.

Le constructeur de la sous-classe doit donc être capable de définir non seulement ses propres attributs, mais aussi de transmettre les valeurs requises au constructeur de la surclasse. C'est pourquoi la signature du constructeur dans la sous-classe contient souvent toute la signature du constructeur qu'il est nécessaire d'appeler.

Séquence de l'implémentation du nouveau constructeur

Dans l'implémentation du nouveau constructeur, il existe une séquence particulière d'opérations que vous devez observer. L'événement le plus important est l'appel au constructeur de la surclasse. Cela est obligatoire et vous appelez la méthode à l'aide de la référence implicite super, comme vous le pouvez lors de l'appel de l'implémentation d'origine d'une méthode redéfinie. Encore une fois, vous n'avez pas besoin de déclarer explicitement super.

Avant d'avoir appelé le constructeur de la surclasse, vous ne devez adresser aucun composant d'instance de l'instance en cours de construction. Vous pouvez adresser des composants statiques de la classe et vérifier l'exactitude des paramètres d'importation du constructeur. S'ils ne sont pas corrects, déclenchez une exception.

Une fois le constructeur de la surclasse exécuté avec succès, vous pouvez vous adresser aux composants d'instance de votre nouvelle instance.

Séquence d'appels de constructeur

La figure illustre la séquence dans laquelle les constructeurs statiques et d'instance sont appelés. L'exemple suppose qu'un programme souhaite instancier la classe avion passager et que la classe avion n'a pas été adressée précédemment.

Lorsque le programme tente de créer une instance de la classe avion passager, le système d'exécution appelle automatiquement les constructeurs statiques de manière séquentielle, en commençant par le haut de la hiérarchie d'héritage. Une fois que tous les constructeurs statiques ont été exécutés, le système d'exécution appelle le constructeur d'instance de la sous-classe, qui appelle à son tour le constructeur d'instance de la surclasse.

Essayer : implémentation de l'héritage

  1. Créez une nouvelle classe qui implémente l'interface IF_OO_ADT_CLASSRUN.
  2. Passez à l'onglet Types locaux et copiez l'extrait de code suivant dans l'éditeur :
    Code Snippet
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
    CLASS lcl_plane DEFINITION. PUBLIC SECTION. TYPES: BEGIN OF ts_attributes, name TYPE string, value TYPE string, END OF ts_attributes, * declare table - do not allow the same attribute to be used more than once tt_attributes TYPE SORTED TABLE OF ts_attributes WITH UNIQUE KEY name. METHODS constructor IMPORTING iv_manufacturer TYPE string iv_type TYPE string. METHODS: get_Attributes RETURNING VALUE(rt_Attributes) TYPE tt_attributes. PROTECTED SECTION. DATA manufacturer TYPE string. DATA type TYPE string. PRIVATE SECTION. ENDCLASS. CLASS lcl_plane IMPLEMENTATION. METHOD constructor. manufacturer = iv_manufacturer. type = iv_type. ENDMETHOD. METHOD get_attributes. rt_attributes = VALUE #( ( name = 'MANUFACTURER' value = manufacturer ) ( name = 'TYPE' value = type ) ) . ENDMETHOD. ENDCLASS. CLASS lcl_cargo_plane DEFINITION INHERITING FROM lcl_plane. PUBLIC SECTION. METHODS constructor IMPORTING iv_manufacturer TYPE string iv_type TYPE string iv_cargo TYPE i. METHODS get_attributes REDEFINITION. private section. data cargo type i. ENDCLASS. CLASS lcl_cargo_plane IMPLEMENTATION. METHOD constructor. super->constructor( iv_manufacturer = iv_manufacturer iv_type = iv_type ). cargo = iv_cargo. ENDMETHOD. METHOD get_attributes. * method uses protected attributes of superclass rt_attributes = value #( ( name = 'MANUFACTURER' value = manufacturer ) ( name = 'TYPE' value = type ) ( name ='CARGO' value = cargo ) ). ENDMETHOD. ENDCLASS. CLASS lcl_passenger_plane DEFINITION INHERITING FROM lcl_Plane. PUBLIC SECTION. METHODS constructor IMPORTING iv_manufacturer TYPE string iv_type TYPE string iv_seats TYPE i. METHODS get_Attributes REDEFINITION. private section. data seats type i. ENDCLASS. CLASS lcl_passenger_plane IMPLEMENTATION. METHOD constructor. super->constructor( iv_manufacturer = iv_manufacturer iv_type = iv_type ). ENDMETHOD. METHOD get_attributes. * Redefinition uses call of superclass implementation rt_attributes = super->get_attributes( ). rt_Attributes = value #( base rt_attributes ( name = 'SEATS' value = seats ) ). ENDMETHOD. ENDCLASS.
  3. Activez la classe en appuyant sur Ctrl + F3.
  4. Familiarisez-vous avec le code source à l'aide des fonctionnalités de l'éditeur telles que la documentation F2 et les fonctions de navigation.

    Remarque

    Il n'y a pas de code exécutable dans cet exemple.

Utilisation des composants abstraits et finaux

Vous pouvez déclarer une classe comme abstraite. Cela signifie qu'un programme ne peut pas l'instancier. Dans notre exemple avec les avions, les avions de passagers et les avions cargo, vous pouvez décider que, dans le monde réel, il n'y a que des avions de passagers et des avions cargo. Cependant, du point de vue de la modélisation logicielle, il est utile d'avoir la classe lcl_plane pour contenir les composants que les avions cargo et les avions passagers ont en commun. En utilisant la classe abstraite, vous pouvez implémenter tous les composants communs dans la classe plane sans avoir à craindre que quelqu'un puisse créer des instances de la classe par erreur.

Si une classe est abstraite, vous pouvez toujours accéder à ses composants statiques. Il s'agit des points suivants :

  • Méthodes statiques
  • Attributs statiques
  • Constantes
  • Définitions de types

Bien que vous puissiez implémenter les méthodes d'une classe abstraite, vous pouvez également déclarer une méthode individuelle comme abstraite. Dans ce cas, il n'existe aucune implémentation pour celle-ci dans la classe dans laquelle elle est déclarée. Notez que vous ne pouvez déclarer une méthode abstraite que dans une classe abstraite.

Les sous-classes de la classe abstraite ne peuvent être instanciées qu'une fois la méthode abstraite redéfinie.

Vous pouvez déclarer une classe comme FINAL. Cela signifie qu'il ne peut pas avoir de sous-classes.

Dans une classe qui n'est pas elle-même finale, vous pouvez déclarer les méthodes comme finales. Cela signifie que, bien que la classe elle-même puisse avoir des sous-classes, la méthode elle-même ne peut pas être redéfinie. Vous pouvez le faire si une méthode contient un contrôle des autorisations. Sinon, une sous-classe peut redéfinir la méthode et ignorer le contrôle des autorisations.

Implémenter héritage

Vous remarquez que vos classes locales LCL_PASSENGER_FLIGHT et LCL_CARGO_FLIGHT ont beaucoup en commun et contiennent des implémentations redondantes. Vous réalisez que du point de vue du modèle, vous pouvez percevoir les vols de passagers et les vols de fret comme deux spécialisations de vols en général. Par conséquent, vous introduisez une surclasse commune LCL_FLIGHT avec les définitions et implémentations communes.

Modèle :

  • /LRN/CL_S4D401_ACS_AUTH_CHECK (classe globale)

Solution :

  • /LRN/CL_S4D401_OOS_INHERITANCE (classe globale)

Tâche 1: Copier modèle (facultatif)

Copiez la classe de modèle /LRN/CL_S4D401_ACS_AUTH_CHECK. Si vous avez terminé l'exercice précédent, vous pouvez ignorer cette tâche et continuer à modifier votre classe ZCL_##_SOLUTION.

Étapes

  1. Copiez la classe /LRN/CL_S4D401_ACS_AUTH_CHECK dans une classe de votre propre package (nom proposé : ZCL_##_SOLUTION, ## correspondant à votre numéro de groupe).

    1. Dans l'explorateur de projet, cliquez avec le bouton droit de la souris sur la classe /LRN/CL_S4D401_ACS_AUTH_CHECK pour ouvrir le menu contextuel.

    2. Dans le menu contextuel, sélectionnez Dupliquer....

    3. Saisissez le nom de votre package dans la zone Package. Dans la zone Nom, saisissez ZCL_##_SOLUTION, où ## représente votre numéro de groupe.

    4. Cliquez sur Next.

    5. Confirmez l'ordre de transport et cliquez sur Terminer.

  2. Activez la copie.

    1. Appuyez sur Ctrl + F3 pour activer la classe.

Tâche 2: Définir la surclasse

Définissez une nouvelle classe locale LCL_FLIGHT et laissez les classes locales LCL_PASSENGER_FLIGHT et LCL_CARGO_FLIGHT en hériter. Comparez les deux sous-classes et déplacez les attributs et définitions de méthode identiques dans les deux classes vers la surclasse.

Étapes

  1. Dans votre classe globale ZCL_##_SOLUTION, utilisez un modèle de code pour définir une nouvelle classe locale LCL_FLIGHT.

    Remarque

    Assurez-vous de définir la nouvelle classe au début du code source dans l'onglet Types locaux afin de pouvoir la référencer dans les classes locales existantes.
    1. Dans votre classe globale ZCL_##_SOLUTION, passez à l'onglet Types locaux.

    2. Au début du code source, tapez lcl et appuyez sur Ctrl + Espace pour appeler la saisie semi-automatique du code source.

    3. Dans la liste des complétions suggérées, sélectionnez lcl - Classe locale.

    4. Alors que lcl_ est toujours en surbrillance, saisissez lcl_flight pour ajuster le nom de classe dans la définition et la partie implémentation.

    5. Le modèle de code doit avoir ajouté le code suivant :

      ABAP
      123456789
      CLASS lcl_flight DEFINITION CREATE PRIVATE. PUBLIC SECTION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_flight IMPLEMENTATION. ENDCLASS.
  2. Assurez-vous qu'il n'est pas possible de créer des instances de LCL_FLIGHT.

    1. Supprimez l'option CREATE PRIVATE et remplacez-la par une option ABSTRACT.

    2. Assurez-vous que votre code ressemble à ceci :

      ABAP
      12
      * CLASS lcl_flight DEFINITION CREATE PRIVATE. CLASS lcl_flight DEFINITION ABSTRACT.
  3. Laissez la classe locale LCL_PASSENGER_FLIGHT hériter de la classe locale LCL_FLIGHT.

    1. Faites défiler vers le bas jusqu'à la partie définition de la classe locale LCL_PASSENGER_FLIGHT.

    2. Adaptez le code comme suit :

      ABAP
      12
      CLASS lcl_passenger_flight DEFINITION INHERITING FROM lcl_flight.
  4. Corrigez les erreurs de syntaxe "Dans la méthode du constructeur, les attributs d'instance … ne sont accessibles qu'après l'appel du constructeur de la surclasse …" en ajoutant super->constructor( ). au début de l'implémentation de la méthode CONSTRUCTOR dans la sous-classe LCL_PASSENGER_FLIGHT.

    Remarque

    Nous examinerons plus en détail la logique du constructeur plus tard dans cet exercice.
    1. Adaptez le code comme suit :

      ABAP
      12
      METHOD constructor. super->constructor( ).
  5. Utilisez un correctif rapide pour déplacer ("extraire") les composants publics suivants de la sous-classe LCL_PASSENGER_FLIGHT vers la surclasse LCL_FLIGHT :

    • Attribut carrier_id
    • ID de connexion de l'attribut
    • Attribut flight_date
    • Type de structure ST_CONNECTION_DETAILS
    • Méthode GET_CONNECTION_DETAILS

    Remarque

    Cette étape entraîne une erreur de syntaxe dans l'implémentation de la méthode GET_CONNECTION_DETAILS déplacée car elle accède à un composant qui n'est pas encore disponible dans la surclasse LCL_FLIGHT. Cette erreur sera corrigée à l'étape suivante.
    1. Dans la partie définition de la classe locale LCL_PASSENGER_FLIGHT, placez le curseur sur carrier_id et sélectionnez Ctrl + 1 pour afficher la liste des solutions rapides disponibles.

    2. Dans la liste des solutions rapides disponibles, sélectionnez Pull-Up carrier_id pour la surclasse lcl_flight.

    3. Répétez cette opération pour les autres composants listés ci-dessus.

    4. La partie définition de la surclasse LCL_FLIGHT doit maintenant ressembler à ceci :

      ABAP
      1234567891011121314151617181920212223
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. TYPES: BEGIN OF st_connection_details, airport_from_id TYPE /dmo/airport_from_id, airport_to_id TYPE /dmo/airport_to_id, departure_time TYPE /dmo/flight_departure_time, arrival_time TYPE /dmo/flight_departure_time, duration TYPE i, END OF st_connection_details. DATA carrier_id TYPE /dmo/carrier_id READ-ONLY. DATA connection_id TYPE /dmo/connection_id READ-ONLY. DATA flight_date TYPE /dmo/flight_date READ-ONLY. METHODS: get_connection_details RETURNING VALUE(r_result) TYPE st_connection_details. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS.
  6. Utilisez un correctif rapide pour déplacer ("extraire") les composants privés suivants de la sous-classe LCL_PASSENGER_FLIGHT vers la surclasse LCL_FLIGHT :

    • Type de planification d'attribut
    • Attribut connection_details
    1. Dans la partie définition de la classe locale LCL_PASSENGER_FLIGHT, positionnez le curseur sur planetype et sélectionnez Ctrl + 1 pour afficher la liste des solutions rapides disponibles.

    2. Dans la liste des solutions rapides disponibles, sélectionnez Pull-Up planetype pour la surclasse lcl_flight.

    3. Répétez cette opération pour l'attribut connection_details.

    4. La partie définition de la surclasse LCL_FLIGHT doit maintenant ressembler à ceci :

      ABAP
      1234567891011121314151617181920212223242526
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. TYPES: BEGIN OF st_connection_details, airport_from_id TYPE /dmo/airport_from_id, airport_to_id TYPE /dmo/airport_to_id, departure_time TYPE /dmo/flight_departure_time, arrival_time TYPE /dmo/flight_departure_time, duration TYPE i, END OF st_connection_details. DATA carrier_id TYPE /dmo/carrier_id READ-ONLY. DATA connection_id TYPE /dmo/connection_id READ-ONLY. DATA flight_date TYPE /dmo/flight_date READ-ONLY. METHODS: get_connection_details RETURNING VALUE(r_result) TYPE st_connection_details. PROTECTED SECTION. DATA planetype TYPE /dmo/plane_type_id. DATA connection_details TYPE st_connection_details. PRIVATE SECTION. ENDCLASS.
  7. Laissez la classe locale LCL_CARGO_FLIGHT hériter de la classe locale LCL_FLIGHT.

    1. Faites défiler jusqu'à la partie définition de la classe locale LCL_CARGO_FLIGHT.

    2. Adaptez le code comme suit :

      ABAP
      12
      CLASS lcl_cargo_flight DEFINITION INHERITING FROM lcl_flight.
  8. Commentez ou supprimez les définitions redondantes de la classe locale LCL_CARGO_FLIGHT.

    Astuce

    Utilisez les erreurs de syntaxe dans la vue Problèmes pour accéder aux définitions redondantes.
    1. Dans la vue Problèmes, double-cliquez sur Erreur de syntaxe Il existe déjà un type appelé "ST_CONNECTION_DETAILS".

    2. Supprimez ou commentez la définition du type de structure ST_CONNECTION_DETAILS dans la classe locale LCL_CARGO_FLIGHT.

    3. Répétez cette opération pour les autres composantes déjà définies dans la surclasse LCL_FLIGHT.

    Remarque

    N'oubliez pas de supprimer ou de commenter également l'implémentation de la méthode GET_CONNECTION_DETAILS.
  9. Corrigez les erreurs de syntaxe "Dans la méthode du constructeur, les attributs d'instance … ne sont accessibles qu'après l'appel du constructeur de la surclasse …" en ajoutant super->constructor( ). au début de l'implémentation de la méthode CONSTRUCTOR dans la sous-classe LCL_CARGO_FLIGHT.

    1. Adaptez le code comme suit :

      ABAP
      12
      METHOD constructor. super->constructor( ).

Tâche 3: Redéfinir une méthode

Définissez une méthode GET_DESCRIPTION dans la surclasse et redéfinissez-la dans les sous-classes. Déplacez les parties communes de l'implémentation vers la surclasse et conservez les parties spécifiques dans les sous-classes.

Étapes

  1. Dans la surclasse LCL_FLIGHT, définissez une méthode d'instance publique GET_DESCRIPTION avec les mêmes paramètres que dans les sous-classes.

    Astuce

    Copiez la définition de méthode à partir de l'une des sous-classes.
    1. Adaptez le code comme suit :

      ABAP
      123456
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. METHODS get_description RETURNING VALUE(r_result) TYPE string_table.
  2. Dans les classes locales LCL_PASSENGER_FLIGHT et LCL_CARGO_FLIGHT, remplacez les définitions de la méthode GET_DESCRIPTION par des redéfinitions.

    Astuce

    Utilisez les erreurs de syntaxe dans la vue Problèmes pour accéder aux définitions de méthodes.
    1. Dans la partie de définition des deux sous-classes, ajustez le code comme suit :

      ABAP
      1234
      * METHODS get_description * RETURNING * VALUE(r_result) TYPE string_table. METHODS get_description REDEFINITION.
  3. Utilisez un quickfix pour ajouter une implémentation vide pour la nouvelle méthode GET_DESCRIPTION à la classe locale LCL_FLIGHT.

    1. Dans la définition de la classe locale LCL_FLIGHT, placez le curseur sur get_description et appuyez sur Ctrl + 1 pour appeler les solutions rapides disponibles. Vous pouvez également sélectionner l'icône d'erreur avec l'ampoule à gauche du code.

    2. Dans la liste de propositions, sélectionnez Ajouter implémentation pour get_description.

  4. Dans la classe locale LCL_PASSENGER_FLIGHT, ajustez l'implémentation de la méthode GET_DESCRIPTION. Au début de l'implémentation, appelez l'implémentation à partir de la surclasse et archivez le résultat dans le paramètre r_result.

    1. Ajoutez le code suivant :

      ABAP
      1
      r_result = super->get_description( ).
  5. Déplacez le code qui gère les valeurs ​​des attributs hérités suivants de la sous-classe LCL_PASSENGER_FLIGHT vers l'implémentation de la méthode GET_DESCRIPTION dans la surclasse LCL_FLIGHT : carrier_id, connection_id, flight_date, connection_details-airport_from_id, connection_details-airport_to_id, et planetype.

    1. Mettez en surbrillance la déclaration et la préparation de la variable locale txt ainsi que les deux instructions APPEND pour la variable txt et l'attribut planetype, puis appuyez sur Ctrl + C pour copier l'extrait de code dans le presse-papiers.

    2. Appuyez sur Ctrl + < pour ajouter un signe de commentaire au début des lignes de code sélectionnées.

    3. Passez à l'implémentation de la méthode GET_DESCRIPTION dans la classe locale LCL_FLIGHT, placez le curseur entre les instructions METHOD … et ENDMETHOD et appuyez sur Ctrl + V pour insérer l'extrait de code.

    4. L'implémentation dans la surclasse doit alors ressembler à ceci :

      ABAP
      12345678910111213
      METHOD get_description. DATA txt TYPE string. txt = 'Flight &carrid& &connid& on &date& from &from& to &to&'(005). txt = replace( val = txt sub = '&carrid&' with = carrier_id ). txt = replace( val = txt sub = '&connid&' with = connection_id ). txt = replace( val = txt sub = '&date&' with = |{ flight_date DATE = USER }| ). txt = replace( val = txt sub = '&from&' with = connection_details-airport_from_id ). txt = replace( val = txt sub = '&to&' with = connection_details-airport_to_id ). APPEND txt TO r_result. APPEND |{ 'Planetype:'(006) } { planetype }| TO r_result. ENDMETHOD.
  6. Dans la classe locale LCL_CARGO_FLIGHT, ajustez l'implémentation de la méthode GET_DESCRIPTION en conséquence : appelez l'implémentation héritée de la méthode GET_DESCRIPTION et supprimez ou commentez les instructions APPEND redondantes.

    1. Adaptez le code comme suit :

      ABAP
      123456789101112
      METHOD get_description. r_result = super->get_description( ). * APPEND |Flight { carrier_id } { connection_id } on { flight_date DATE = USER } | && * |from { connection_details-airport_from_id } to { connection_details-airport_to_id }| * TO r_result. * APPEND |Planetype: { planetype }| * TO r_result. APPEND |Maximum Load: { maximum_load } { load_unit }| TO r_result. APPEND |Free Capacity: { get_free_capacity( ) } { load_unit }| TO r_result. ENDMETHOD.

Tâche 4: Ajouter un constructeur commun

Dans la surclasse LCL_FLIGHT, définissez un constructeur d'instance avec les paramètres d'entrée que les deux constructeurs de sous-classes ont en commun. Ajustez l'appel du constructeur de superclasse dans les sous-classes afin qu'elles transfèrent les paramètres communs. Ensuite, déplacez les parties communes de la logique du constructeur des constructeurs de sous-classes vers le constructeur de superclasse.

Étapes

  1. Dans la surclasse LCL_FLIGHT, définissez une méthode CONSTRUCTOR ayant les mêmes paramètres d'entrée que le CONSTRUCTOR de la sous-classe LCL_PASSENGER_FLIGHT.

    Astuce

    Il n'y a pas de correctif rapide d'extraction pour les méthodes de constructeur d'instance. Copiez et collez plutôt la définition de méthode de la sous-classe vers la surclasse.
    1. Faites défiler jusqu'à la partie définition de la classe locale LCL_PASSENGER_FLIGHT.

    2. Sélectionnez l'instruction METHODS complète pour la méthode CONSTRUCTOR et appuyez sur Ctrl + C pour copier l'extrait de code dans le presse-papiers.

    3. Faites défiler jusqu'à la partie définition de la classe locale LCL_FLIGHT, placez le curseur après l'instruction PUBLIC SECTION et appuyez sur Ctrl + V pour insérer l'extrait de code à partir du presse-papiers.

  2. Ajustez l'appel du constructeur de superclasse dans les sous-classes. Transférez les paramètres d'importation au constructeur de superclasse.

    Astuce

    Utilisez les erreurs de syntaxe dans la vue Problèmes pour naviguer vers les appels du constructeur de surclasse.
    1. Dans les deux constructeurs de sous-classes, ajustez le code comme suit :

      ABAP
      123456
      METHOD constructor. super->constructor( i_carrier_id = i_carrier_id i_connection_id = i_connection_id i_flight_date = i_flight_date ).
  3. Utilisez un correctif rapide pour ajouter une implémentation vide pour le constructeur de superclasse.

    1. Dans la définition de la classe locale LCL_FLIGHT, placez le curseur sur constructor et appuyez sur Ctrl + 1 pour appeler les solutions rapides disponibles.

    2. Dans la liste de propositions, sélectionnez Ajouter implémentation pour constructeur.

  4. Déplacez les valorisations pour les attributs hérités carrier_id, connection_id et flight_date des constructeurs de sous-classes vers le constructeur de superclasse.

    1. Naviguez vers l'implémentation de la méthode CONSTRUCTOR dans la classe locale LCL_PASSENGER_FLIGHT.

    1. Sélectionnez les valorisations pour les attributs hérités carrier_id, connection_id et flight_date et appuyez sur Ctrl + C pour copier l'extrait de code dans le presse-papiers.

    2. Appuyez sur Ctrl + < pour ajouter un signe de commentaire au début des lignes de code sélectionnées.

    3. Passez à l'implémentation de la méthode CONSTRUCTOR dans la classe locale LCL_FLIGHT, placez le curseur entre METHOD … et ENDMETHOD et appuyez sur Ctrl + V pour insérer l'extrait de code.

    4. L'implémentation dans la surclasse doit alors ressembler à ceci :

      ABAP
      12345
      METHOD constructor. me->carrier_id = i_carrier_id. me->connection_id = i_connection_id. me->flight_date = i_flight_date. ENDMETHOD.
    5. Passez à l'implémentation de la méthode CONSTRUCTOR dans la classe locale LCL_CARGO_FLIGHT et supprimez ou commentez les valorisations redondantes.

  5. Activez et testez votre classe globale comme application de console. Déboguez l'instanciation de la classe locale LCL_PASSENGER_FLIGHT et l'appel de la méthode GET_DESCRIPTION.

    1. Appuyez sur Ctrl + F3.

    2. Appuyez sur F9.