Análise e teste de código
Utilização correta de tipos de dados e conversões de tipo
Processamento de campos de caracteres
Uso de push-down de código no ABAP SQL
Melhorar o desempenho da tabela interna
Implementar verificações de autorização
Projetando código efetivo orientado a objetos
Definir e trabalhar com classes de exceção
Adicionar documentação à codificação ABAP

Utilizar interfaces

Objective

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

Utilização de interface

Declarar uma referência de interface

Você pode utilizar interfaces como um tipo de referência para declarar uma variável de referência. Como você aprendeu anteriormente, é possível utilizar variáveis de referência para criar e gerenciar as instâncias de uma classe. Uma vez que não é possível instanciar uma interface, você pode estar se perguntando quais tipos de objetos pode gerenciar utilizando uma referência de interface.

As referências de interface podem conter referências a instâncias de qualquer classe que implemente a interface da mesma forma que uma variável de referência com o tipo de uma classe superior pode conter referências a instâncias de qualquer subclasse. (Se você imaginar agora que a classe superior é abstrata, você tem uma situação idêntica de um tipo que não pode ser instanciado mantendo referências a instâncias de outras classes relacionadas a ela).

Ao utilizar uma variável com o tipo de uma classe superior para gerenciar uma instância de uma de suas subclasses, você só poderá acessar os componentes que estiverem definidos na classe superior. De modo semelhante, quando você utiliza uma referência de interface para administrar uma instância de uma classe que implementa a interface, você só pode acessar os componentes definidos na interface. Isso significa que o desenvolvedor de uma determinada estrutura de classes pode enviar interfaces que fornecem uma visão particular de uma classe em vez de expor cada coisa que a classe pode fazer.

Você pode chamar um método de uma interface utilizando uma variável de referência com o tipo da classe. Neste caso, você deve utilizar o nome completo do método (incluindo o nome da interface). Se você tiver definido um alias para o método, pode utilizá-lo. Ao chamar um método de interface utilizando uma referência de interface, o nome da interface será derivado do tipo da variável de referência, e você não precisará especificar o nome da interface antes do nome do método.

Casting com referências de interface

A atribuição de referências a objetos a uma referência de interface também é um cast. Você analisará o objeto de aluguel ou de companhia aérea como se fosse um parceiro de negócios. É sempre possível atribuir uma instância da classe de implementação para uma referência de interface. Este é um up-cast, e é garantido pelo fato de que a classe implementa a interface. Todavia, você não pode atribuir um objeto de uma referência de interface a uma referência com o tipo de uma classe de implementação, uma vez que a verificação de sintaxe não pode ver se os objetos de tempo de execução em si serão compatíveis. A atribuição rental = partner funcionaria se o objeto na referência de interface realmente for uma instância de lcl_car_rental, mas se for uma instância de outra classe de implementação, você causaria um erro em tempo de execução.

Aqui temos um down-cast da mesma forma que o detectado na herança. A solução aqui é a mesma. Se você precisar atribuir uma referência a objetos de uma variável de referência com o tipo de uma interface a uma com o tipo de uma classe (para que você possa acessar funcionalidades específicas da classe), deve usar o operador CAST. A solução correta neste caso seria:

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

Testar: utilização da interface

  1. Crie uma nova classe que implemente a interface IF_OO_ADT_CLASSRUN.
  2. Mude para a guia Tipos locais e copie o seguinte snippet de código para o editor:
    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. Mude para a ficha Classe global e cole o seguinte snippet de código na implementação do método 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.

Chamar métodos de interface

No exercício anterior, você definiu a interface LIF_OUTPUT e implementou a mesma nas classes LCL_CARRIER e LCL_FLIGHT. Na sua classe global, o método get_output da interface LIF_OUTPUT já foi chamado para a instância de agente de frete criada. Neste exercício, você também chamará agora o método da interface get_output para as instâncias das classes LCL_PASSENGER_FLIGHT e LCL_CARGO_FLIGHT.

Modelo:

  • /LRN/CL_S4D401_OOS_INTERFACE (classe global)

Solução:

  • /LRN/CL_S4D401_OOS_INTF_USAGE (classe global)

Tarefa 1: Copiar modelo (opcional)

Copie a classe modelo /LRN/CL_S4D401_OOS_INTERFACE. Se você tiver concluído o exercício anterior, pode ignorar esta tarefa e continuar processando sua classe ZCL_##_SOLUTION.

Etapas

  1. Copie a classe /LRN/CL_S4D401_OOS_INTERFACE para uma classe em seu próprio pacote (nome sugerido: ZCL_##_SOLUTION, onde ## representa seu número de grupo).

    1. No Explorador de projetos, clique com o botão direito do mouse na classe /LRN/CL_S4D401_OOS_INTERFACE para abrir o menu de contexto.

    2. No menu de contexto, selecione Duplicar....

    3. Insira o nome do seu pacote no campo Pacote. No campo Nome, insira ZCL_##_SOLUTION, em que ## representa seu número de grupo.

    4. Selecione Avançar.

    5. Confirme a ordem de transporte e selecione Concluir.

  2. Ative a cópia.

    1. Pressione Ctrl + F3 para ativar a classe.

Tarefa 2: Utilizar a interface

Na classe local LCL_FLIGHT, modifique a visibilidade do método de instância GET_DESCRIPTION para forçar os usuários externos a chamar o método GET_OUTPUT. Em seguida, ajuste a implementação do método IF_OO_ADT_CLASSRUN~MAIN de modo correspondente.

Etapas

  1. Na classe local LCL_FLIGHT, utilize uma correção rápida para modificar a visibilidade do método de instância GET_DESCRIPTION para protegido.

    1. Navegue para a definição do método GET_DESCRIPTION na classe local LCL_FLIGHT.

    2. Na instrução METHODS, posicione o cursor em get_description e pressione Ctrl + 1 para chamar as soluções rápidas disponíveis.

    3. Na lista de soluções rápidas disponíveis, selecione Tornar get_description protegido.

  2. Modifique a visibilidade das redefinições de GET_DESCRIPTION nas subclasses LCL_PASSENGER_FLIGHT e LCL_CARGO_FLIGHT.

    Nota

    Você deve copiar as redefinições manualmente. Ainda não há uma correção rápida para alterar a visibilidade das redefinições.
    1. Navegue para a redefinição do método GET_DESCRIPTION na classe local LCL_PASSENGER_FLIGHT.

    2. Selecione a instrução METHODS e pressione Ctrl + X.

    3. Posicione o cursor na linha seguinte após a instrução PROTECTED SECTION e pressione Ctrl + V.

    4. Repita isso na classe local LCL_CARGO_FLGHT.

  3. Ajuste a implementação do método IF_OO_ADT_CLASSRUN~MAIN onde o método GET_DESCRIPTION é chamado. Substitua o método GET_DESCRIPTION pelo método de interface GET_OUTPUT.

    Dica

    Utilize as duas mensagens de erro na visão Problemas para navegar para os locais onde o método GET_DESCRIPTION ainda é chamado.
    1. Ajuste o código da seguinte forma:

      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. Ajuste o código da seguinte forma:

      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. Defina um alias para o método de interface LIF_OUTPUT~GET_OUTPUT para facilitar a chamada do método (nome de alias sugerido: GET_OUTPUT).

    Dica

    Se você definir o alias na classe superior LCL_FLIGHT, ele será herdado pelas duas subclasses.
    1. Navegue para a definição da classe local LCL_FLIGHT.

    2. Ajuste o código da seguinte forma:

      ABAP
      1234
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. INTERFACES lif_output. ALIASES get_output for lif_output~get_output.
  5. Retorne à implementação do método IF_OO_ADT_CLASSRUN~MAIN e substitua LIF_OUTPUT~GET_OUTPUT pelo alias.

    1. Ajuste o código da seguinte forma:

      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. Ajuste o código da seguinte forma:

      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. Ative e teste sua classe global como aplicativo de console.

    1. Pressione Ctrl + F3.

    2. Pressione F9.