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

Utilisation d'interfaces

Objective

After completing this lesson, you will be able to utilisez les interfaces.

Utilisation de l'interface

Déclaration d'une référence d'interface

Vous pouvez utiliser des interfaces comme type de référence pour déclarer une variable de référence. Comme vous l'avez appris précédemment, vous utilisez des variables de référence pour créer et gérer les instances d'une classe. Comme il n'est pas possible d'instancier une interface, vous vous demandez peut-être quels types d'objets vous pouvez gérer à l'aide d'une référence d'interface.

Les références d'interface peuvent contenir des références à des instances de n'importe quelle classe qui implémente l'interface de la même manière qu'une variable de référence du type d'une surclasse peut contenir des références à des instances de n'importe quelle sous-classe. (Si vous imaginez maintenant que la surclasse est abstraite, vous avez une situation identique d'un type qui ne peut pas être instancié contenant des références à des instances d'autres classes qui lui sont liées).

Lorsque vous utilisez une variable avec le type d'une surclasse pour gérer une instance de l'une de ses sous-classes, vous pouvez uniquement accéder aux membres qui sont définis dans la surclasse. De la même manière, lorsque vous utilisez une référence d'interface pour gérer une instance d'une classe qui implémente l'interface, vous ne pouvez accéder qu'aux composants définis dans l'interface. Cela signifie que le développeur d'une structure particulière de classes peut expédier des interfaces qui fournissent une vue particulière d'une classe au lieu d'exposer chaque chose que la classe peut faire.

Vous pouvez appeler une méthode à partir d'une interface à l'aide d'une variable de référence avec le type de la classe. Dans ce cas, vous devez utiliser le nom complet de la méthode (y compris le nom de l'interface). Si vous avez défini un alias pour la méthode, vous pouvez l'utiliser. Lorsque vous appelez une méthode d'interface à l'aide d'une référence d'interface, le nom de l'interface est déduit du type de la variable de référence et vous n'avez pas besoin d'indiquer le nom de l'interface avant le nom de la méthode.

Casting avec références d'interface

L'affectation de références d'objet à une référence d'interface est également un transtypage ; vous examinez l'objet loué ou porteur comme s'il s'agissait d'un partenaire. Vous pouvez toujours affecter une instance de la classe d'implémentation à une référence d'interface. Il s'agit d'un transtypage ascendant, garanti par le fait que la classe implémente l'interface. Cependant, vous ne pouvez pas affecter un objet d'une référence d'interface à une référence du type d'une classe d'implémentation car le contrôle syntaxique ne peut pas déterminer si les objets d'exécution réels seront compatibles. L'affectation rental = partner fonctionnerait si l'objet dans la référence d'interface est réellement une instance de lcl_car_rent, mais s'il s'agit d'une instance d'une autre classe d'implémentation, vous provoquez une erreur d'exécution.

Ici, nous avons un down-cast de la même manière que nous l'avons rencontré dans l'héritage. La solution ici est la même. Si vous devez affecter une référence objet d'une variable de référence avec le type d'une interface à une référence avec le type d'une classe (afin de pouvoir accéder à des caractéristiques spécifiques de la classe), vous devez utiliser l'opérateur CAST. Dans ce cas, la solution correcte serait :

ABAP
123
IF partner IS INSTANCE OF lcl_car_rental. rental = CAST #( partner ). ENDIF.

Essayer : utilisation de l'interface

  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
    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
    INTERFACE lif_partner. METHODS get_partner_attributes. ENDINTERFACE. CLASS lcl_travel_Agency DEFINITION. PUBLIC SECTION. ENDCLASS. CLASS lcl_airline DEFINITION. PUBLIC SECTION. INTERFACES lif_Partner. TYPES: BEGIN OF ts_detail, name TYPE string, value TYPE string, END OF ts_detail, tt_Details TYPE SORTED TABLE OF ts_detail WITH UNIQUE KEY name. METHODS get_details RETURNING VALUE(rt_details) TYPE tt_details. ENDCLASS. CLASS lcl_car_Rental DEFINITION. PUBLIC SECTION. interfaces lif_Partner. TYPES: BEGIN OF ts_info, name TYPE c LENGTH 20, value TYPE c LENGTH 20, END OF ts_info, tt_Info TYPE SORTED TABLE OF ts_info WITH UNIQUE KEY name. METHODS get_information RETURNING VALUE(rt_details) TYPE tt_info. ENDCLASS. CLASS lcl_airline IMPLEMENTATION. METHOD get_details. ENDMETHOD. METHOD lif_partner~get_partner_attributes. ENDMETHOD. ENDCLASS. CLASS lcl_car_rental IMPLEMENTATION. METHOD get_information. ENDMETHOD. METHOD lif_partner~get_partner_attributes. ENDMETHOD. ENDCLASS.
  3. Passez à l'onglet Classe globale et collez l'extrait de code suivant dans l'implémentation de la méthode if_oo_adt_classrun~main( ).
    Code Snippet
    12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849
    CLASS zcl_s4d401_interfaces_2 DEFINITION PUBLIC FINAL CREATE PUBLIC . PUBLIC SECTION. INTERFACES if_oo_adt_classrun . PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS zcl_s4d401_interfaces_2 IMPLEMENTATION. METHOD if_oo_adt_classrun~main. DATA car_rental TYPE REF TO lcl_car_rental. DATA airline TYPE REF TO lcl_airline. DATA agency TYPE REF TO lcl_travel_agency. DATA partners TYPE TABLE OF REF TO lif_partner. agency = NEW #( ). car_rental = NEW #( iv_name = 'ABAP Autos' iv_contact_person = 'Mr Jones' iv_has_hgv = abap_true ). agency->add_partner( car_rental ). airline = NEW #( iv_name = 'Fly Happy' iv_contact_person = 'Ms Meyer' iv_city = 'Frankfurt' ). agency->add_partner( airline ). LOOP AT agency->get_partners( ) INTO DATA(partner). out->write( partner->get_partner_attributes( ) ). ENDLOOP. ENDMETHOD. ENDCLASS.

Appeler méthodes d'interface

Dans l'exercice précédent, vous avez défini l'interface LIF_OUTPUT et l'avez implémentée dans les classes LCL_CARRIER et LCL_FLIGHT. Dans votre classe globale, la méthode get_output de l'interface LIF_OUTPUT est déjà appelée pour l'instance de transporteur créée. Dans cet exercice, vous allez maintenant également appeler la méthode d'interface get_output pour les instances des classes LCL_PASSENGER_FLIGHT et LCL_CARGO_FLIGHT.

Modèle :

  • /LRN/CL_S4D401_OOS_INTERFACE (classe globale)

Solution :

  • /LRN/CL_S4D401_OOS_INTF_USAGE (classe globale)

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

Copiez la classe de modèle /LRN/CL_S4D401_OOS_INTERFACE. 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_OOS_INTERFACE dans une classe de votre propre package (nom proposé : ZCL_##_SOLUTION, ## correspondant à votre numéro de groupe).

    1. Dans l'explorateur de projets, cliquez avec le bouton droit de la souris sur la classe /LRN/CL_S4D401_OOS_INTERFACE 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: Utilisation de l'interface

Dans la classe locale LCL_FLIGHT, modifiez la visibilité de la méthode d'instance GET_DESCRIPTION pour forcer les utilisateurs externes à appeler la méthode GET_OUTPUT à la place. Adaptez ensuite l'implémentation de la méthode IF_OO_ADT_CLASSRUN~MAIN en conséquence.

Étapes

  1. Dans la classe locale LCL_FLIGHT, utilisez un correctif rapide pour modifier la visibilité de la méthode d'instance GET_DESCRIPTION en "Protégé".

    1. Naviguez vers la définition de la méthode GET_DESCRIPTION dans la classe locale LCL_FLIGHT.

    2. Dans l'instruction METHODS, placez le curseur sur get_description et appuyez sur Ctrl + 1 pour appeler les solutions rapides disponibles.

    3. Dans la liste des solutions rapides disponibles, sélectionnez Définir get_description comme protégé.

  2. Modifiez la visibilité des redéfinitions de GET_DESCRIPTION dans les sous-classes LCL_PASSENGER_FLIGHT et LCL_CARGO_FLIGHT.

    Remarque

    Vous devez copier les redéfinitions manuellement. Il n’y a pas encore de correctif rapide pour modifier la visibilité des redéfinitions.
    1. Naviguez vers la redéfinition de la méthode GET_DESCRIPTION dans la classe locale LCL_PASSENGER_FLIGHT.

    2. Sélectionnez l'instruction METHODS et appuyez sur Ctrl + X.

    3. Placez le curseur sur la ligne suivante après l'instruction PROTECTED SECTION et appuyez sur Ctrl + V.

    4. Répétez cette opération dans la classe locale LCL_CARGO_FLGHT.

  3. Adaptez l'implémentation de la méthode IF_OO_ADT_CLASSRUN~MAIN dans laquelle la méthode GET_DESCRIPTION est appelée. Remplacez la méthode GET_DESCRIPTION par la méthode d'interface GET_OUTPUT.

    Astuce

    Utilisez les deux messages d'erreur dans la vue Problèmes pour accéder aux emplacements où la méthode GET_DESCRIPTION est encore appelée.
    1. Adaptez le code comme suit :

      ABAP
      123
      out->write( name = |Found a suitable passenger flight in { days_later } days:| * data = pass_flight->get_description( ) ). data = pass_flight->lif_output~get_output( ) ).
    2. Adaptez le code comme suit :

      ABAP
      123
      out->write( name = |Found a suitable cargo flight in { days_later2 } days:| * data = cargo_flight->get_description( ) ). data = cargo_flight->lif_output~get_output( ) ).
  4. Définissez un alias pour la méthode d'interface LIF_OUTPUT~GET_OUTPUT afin de faciliter l'appel de la méthode (nom d'alias suggéré : GET_OUTPUT).

    Astuce

    Si vous définissez l'alias dans la surclasse LCL_FLIGHT, il est hérité par les deux sous-classes.
    1. Naviguez vers la définition de la classe locale LCL_FLIGHT.

    2. Adaptez le code comme suit :

      ABAP
      1234
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. INTERFACES lif_output. ALIASES get_output for lif_output~get_output.
  5. Revenez à l'implémentation de la méthode IF_OO_ADT_CLASSRUN~MAIN et remplacez LIF_OUTPUT~GET_OUTPUT par l'alias.

    1. Adaptez le code comme suit :

      ABAP
      1234
      out->write( name = |Found a suitable passenger flight in { days_later } days:| * data = pass_flight->get_description( ) ). * data = pass_flight->lif_output~get_output( ) ). data = pass_flight->get_output( ) ).
    2. Adaptez le code comme suit :

      ABAP
      1234
      out->write( name = |Found a suitable cargo flight in { days_later2 } days:| * data = cargo_flight->get_description( ) ). * data = cargo_flight->lif_output~get_output( ) ). data = cargo_flight->get_output( ) ).
  6. Activez et testez votre classe globale comme application de console.

    1. Appuyez sur Ctrl + F3.

    2. Appuyez sur F9.