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

Implementar herança

Objective

After completing this lesson, you will be able to implemente uma classe especializada.

Implementação de herança

Assista a este vídeo para entender o conceito de aulas gerais e mais especializadas.

Herança - A relação "É A"

Na modelagem, falamos sobre especialização. A implementação dessa relação em uma linguagem de programação utiliza o conceito de herança, em que uma nova classe (a subclasse) é derivada de uma existente (a classe superior). Um teste confiável para ver se existe uma relação de herança genuína entre duas classes é tentar dizer que "uma subclasse é uma classe superior". Se isso for claramente verdadeiro, há uma relação de herança. Se claramente não é verdade, ou até soa um pouco estranho, você não tem uma relação de herança e não deve implementar uma, pois provavelmente causará problemas mais abaixo da linha. Ao testar nosso modelo, podemos definitivamente dizer que "um avião de carga é um avião" e "um avião de passageiros é um avião".

Uma classe que herda de uma classe superior automaticamente tem todos os componentes da classe superior. Assim, por exemplo, a classe de avião de passageiros tem um fabricante e um tipo tal como um avião. Isso não deve ser surpreendente, pois um avião de passageiros é um avião. O que pode inicialmente parecer surpreendente é que a classe de avião de passageiros não pode acessar seu próprio fabricante e tipo. Isso porque são atributos privados da classe superior e, como tal, não são acessíveis à subclasse. Mais tarde, você aprenderá uma forma de permitir que uma subclasse acesse os componentes de uma classe superior sem torná-la totalmente pública.

Definir relação de herança

No ABAP, você implementa a herança utilizando o suplemento INHERITING FROM na instrução de definição de classe. Neste exemplo, a classe do avião de passageiros é definida como uma subclasse da classe do avião. Observe que a subclasse conhece sua classe superior, mas a classe de avião não faz ideia de quais subclasses ela tem (se houver).

Uma subclasse pode ter somente uma classe superior direta.

Uma classe superior - qualquer número de subclasses

A classe plana pode ter qualquer número de subclasses, mas não sabe sobre nenhuma delas.

Cada subclasse tem uma única classe superior direta. Ela conhece sua classe superior, mas não tem conhecimento sobre quaisquer classes irmãs (outras classes derivadas da mesma classe superior). Em nosso exemplo, a classe de avião de passageiros não tem conhecimento da classe de avião de carga.

Como ampliar uma subclasse

Depois de declarar uma subclasse, você precisa adicionar novos componentes a ela ou modificar os componentes existentes. Isso é o que transforma a mera cópia da classe de avião em um avião de passageiros ou um avião de carga. Graças à herança, você não precisa implementar a classe do zero - você simplesmente a amplia com os novos componentes de que precisa.

Há três maneiras de fazer isso:

Adicionar novos componentes: você pode declarar novos atributos, tipos, constantes e métodos na classe. Seus nomes não devem coincidir com outros nomes que já tenham sido utilizados para declarar componentes da classe superior. Você também deve garantir que os novos componentes só sejam relevantes para a subclasse, e não para todas as especializações da classe superior. Se você declarar um novo atributo ou método que é geralmente relevante, você deve movê-lo para a classe superior.

Redefinir métodos: quando você chama um método herdado, o sistema de tempo de execução executa a implementação do método a partir da classe superior. No entanto, essa implementação não pode levar em conta quaisquer novos componentes que você tenha declarado na subclasse. Neste caso, você pode redefinir o método. Isso significa que você pode atribuí-lo a uma nova implementação que seja relevante para a subclasse.

Adicione um novo construtor: Construtores garantem que novas instâncias da classe sejam initalizadas corretamente. Ao criar uma instância de uma subclasse, o sistema de tempo de execução sempre executa o construtor da classe superior. Isso garante, por exemplo, que um avião de passageiros tenha um fabricante e um tipo da mesma forma que qualquer outro avião. No entanto, o construtor da classe superior não pode inicializar atributos da subclasse, pois não sabe que eles existem. Por esse motivo, você pode definir um novo construtor para a subclasse.

Declarar novos componentes

Você pode ampliar uma subclasse declarando novos componentes. Elas são visíveis para a própria classe, mas não para a classe superior, e também para nenhuma outra classe que herda da mesma classe superior. Portanto, você precisa considerar se os novos componentes são relevantes apenas para a classe atual ou se eles realmente precisam ser declarados na classe superior.

Componentes protegidos

Mesmo que uma subclasse contenha todos os atributos de sua classe superior, ela não tem permissão para acessar os componentes privados diretamente por si só. Às vezes, isso será necessário, mas, em outros casos, uma classe superior precisará deixar suas subclasses acessarem atributos ou métodos particulares sem deixá-los totalmente públicos. Ele pode fazer isso declarando os mesmos na seção protegida. Os componentes protegidos são visíveis dentro da própria classe, mas também para todas as subclasses.

Na definição de classe, você apresenta a seção protegida utilizando a instrução PROTECTED SECTION. Você deve sempre declarar as áreas de visibilidade na sequência PUBLIC SECTION - PROTECTED SECTION - PRIVATE SECTION.

Você pode deslocar um componente existente de uma classe utilizando uma correção rápida. Para isso, posicione o cursor no nome do componente em ADT e pressione Ctrl + 1 e, em seguida, selecione a solução rápida Tornar <elemento> protegido.

Mover um componente privado para a seção protegida é uma alteração compatível - você ampliou a visibilidade do componente. No entanto, tornar um componente público protegido é uma modificação incompatível e pode causar erros de sintaxe. Isso porque você restringiu a visibilidade do componente, que pode já ter sido utilizado fora da hierarquia de herança.

Redefinir métodos

Classes superiores geralmente contêm métodos que você pode querer usar em uma subclasse, mas suas implementações são inadequadas, já que não levam em conta a natureza particular da subclasse. Por exemplo, o método get_attributes da classe de avião não pode retornar atributos definidos na classe de avião de passageiros. No entanto, a classe de avião de passageiros ainda precisa de um método get_attributes.

No ABAP, você pode resolver esse problema redefinindo o método de instância get_attributes. Ao redefinir um método, você escreve uma nova implementação para ele na subclasse, que leva em consideração coisas que apenas a subclasse pode saber. No entanto, a definição do método permanece exatamente a mesma. Você deve seguir estas regras:

  • o método mantém o mesmo nome.
  • você indica que quer redefinir o método declarando-o na subclasse com o suplemento REDEFINITION.
  • o método tem a mesma visibilidade que a classe superior.
  • Não se deve modificar a assinatura do método.

Não é possível redefinir um método estático.

Implementar a redefinição

Ao implementar a redefinição de um método, você pode chamar a implementação na classe superior. É possível fazer isso utilizando a referência de objeto implícito super, que aponta para a classe superior dentro da instância atual. Dessa forma, você pode reutilizar a implementação de método da classe superior e, em seguida, adicioná-la em sua própria implementação.

Você não precisa declarar a variável de referência super. Ela está disponível automaticamente dentro da implementação de métodos redefinidos.

Chamar o método na classe superior desta forma é opcional. Às vezes, será uma boa ideia. Outras, não valerá a pena.

Nova definição de construtor

Em uma subclasse, você pode definir um novo construtor. Ao contrário de redefinições de método, um construtor pode ter sua própria assinatura. A assinatura de um construtor geralmente contém os mesmos parâmetros que o construtor da classe superior, além de novos parâmetros próprios. Isso ocorre porque o novo construtor de instância tem duas tarefas - primeiro chamar o construtor da classe superior e, em seguida, cuidar da initalização de seus próprios atributos que são específicos da subclasse.

Além de definir um novo construtor, você também pode definir um novo construtor estático em uma subclasse.

Função do construtor

O construtor de uma subclasse tem duas funções: deve garantir que os componentes da classe superior sejam inicializados corretamente e, depois disso, pode definir os valores iniciais dos atributos da subclasse.

Em nosso exemplo, uma vez que um avião de passageiros é um avião, não pode haver nenhuma instância de avião de passageiros, a menos que o construtor da classe de avião tenha executado com êxito para definir o fabricante e o tipo do novo avião de passageiros. Só depois disso é que a classe de avião de passageiros pode definir seus próprios atributos.

O construtor da subclasse deve, portanto, ser capaz de definir não apenas seus próprios atributos, mas também transferir os valores necessários para o construtor da classe superior. É por isso que a assinatura do construtor na subclasse, muitas vezes, contém toda a assinatura do construtor que precisa chamar.

Sequência de implementação de novo construtor

Na implementação do novo construtor, existe uma sequência particular de operações que você deve observar. O evento mais importante é a chamada para o construtor da classe superior. Ela é obrigatória, e você chama o método usando a referência implícita super, da mesma forma que chama a implementação original de um método redefinido. Mais uma vez, você não precisa declarar explicitamente super.

Antes de chamar o construtor da classe superior, você não deve abordar quaisquer componentes da instância que está em construção. Você pode acessar componentes estáticos da classe e verificar a exatidão dos parâmetros de importação do construtor. Se não estiverem corretos, crie uma exceção.

Assim que o construtor da classe superior tiver sido executado corretamente, você poderá acessar os componentes de instância de sua nova instância.

Sequência de chamadas do construtor

A figura ilustra a sequência em que os construtores estático e de instância são chamados. O exemplo pressupõe que um programa quer instanciar a classe de avião de passageiros e que a classe de avião não foi abordada anteriormente.

Quando o programa tenta criar uma instância da classe de avião de passageiros, o sistema de tempo de execução chama automaticamente os construtores estáticos sequencialmente, começando no topo da hierarquia de herança. Assim que todos os construtores estáticos forem executados, o sistema de tempo de execução chamará o construtor de instância da subclasse que, por sua vez, chamará o construtor de instância da classe superior.

Testar: implementação de herança

  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
    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. Ative a classe pressionando Ctrl + F3.
  4. Familiarize-se com o texto fonte usando recursos do editor, como a documentação F2 e as funções de navegação.

    Nota

    Não há código executável neste exemplo.

Utilização de componentes abstratos e finais

Você pode declarar uma classe como abstrata. Isso significa que um programa não pode instanciá-lo. Em nosso exemplo com aviões, aviões de passageiros e aviões de carga, você pode decidir que, no mundo real, existem apenas aviões de passageiros e aviões de carga. No entanto, do ponto de vista da modelagem de software, é útil ter a classe lcl_plane para manter os componentes que os aviões de carga e de passageiros têm em comum. Ao usar a classe abstrata, você pode implementar todos os componentes comuns na classe plana sem ter que se preocupar que alguém possa criar instâncias da classe por engano.

Se uma classe for abstrata, você ainda pode acessar seus componentes estáticos. Estamos falando de:

  • Métodos estáticos
  • Atributos estáticos
  • Constantes
  • Definições de tipo

Embora você possa implementar os métodos de uma classe abstrata, você também pode declarar um método individual como abstrato. Neste caso, não existe nenhuma implementação para ele na classe na qual é declarado. Observe que você só pode declarar um método abstrato em uma classe abstrata.

As subclasses da classe abstrata só podem ser instanciadas depois de o método abstrato ter sido redefinido.

Você pode declarar uma classe como FINAL. Isso significa que ele não pode ter subclasses.

Em uma classe que não é final, você pode declarar métodos como finais. Isso significa que, embora a própria classe possa ter subclasses, o próprio método não pode ser redefinido. Você pode fazer isso se um método contiver uma verificação de autorização. Caso contrário, uma subclasse pode redefinir o método e omitir a verificação de autorização.

Implementar herança

Você percebe que suas classes locais LCL_PASSENGER_FLIGHT e LCL_CARGO_FLIGHT têm muito em comum e contêm implementações redundantes. Você percebe que, de uma perspectiva modelo, você pode perceber voos de passageiros e voos de carga como duas especializações de voos em geral. Por isso, você introduz uma classe superior comum LCL_FLIGHT com as definições e implementações comuns.

Modelo:

  • /LRN/CL_S4D401_ACS_AUTH_CHECK (classe global)

Solução:

  • /LRN/CL_S4D401_OOS_INHERITANCE (classe global)

Tarefa 1: Copiar modelo (opcional)

Copie a classe modelo /LRN/CL_S4D401_ACS_AUTH_CHECK. 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_ACS_AUTH_CHECK 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 na classe /LRN/CL_S4D401_ACS_AUTH_CHECK 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: Definir a classe superior

Defina uma nova classe local LCL_FLIGHT e permita que as classes locais LCL_PASSENGER_FLIGHT e LCL_CARGO_FLIGHT herdem da mesma. Compare as duas subclasses e mova esses atributos e definições de método idênticos em ambas as classes para a classe superior.

Etapas

  1. Em sua classe global ZCL_##_SOLUTION, utilize um modelo de código para definir uma nova classe local LCL_FLIGHT.

    Nota

    Certifique-se de definir a nova classe no início do texto fonte na guia Tipos locais para que você possa referenciá-la nas classes locais existentes.
    1. Em sua classe global ZCL_##_SOLUTION, mude para a guia Tipos locais.

    2. No início do texto fonte, digite lcl e pressione Ctrl + espaço para chamar o code completion.

    3. Na lista de conclusões sugeridas, selecione lcl - Classe local.

    4. Enquanto lcl_ ainda estiver destacado, insira lcl_flight para ajustar o nome da classe na definição e na parte de implementação.

    5. O modelo de código deve ter adicionado o seguinte código:

      ABAP
      123456789
      CLASS lcl_flight DEFINITION CREATE PRIVATE. PUBLIC SECTION. PROTECTED SECTION. PRIVATE SECTION. ENDCLASS. CLASS lcl_flight IMPLEMENTATION. ENDCLASS.
  2. Certifique-se de que não é possível criar instâncias de LCL_FLIGHT.

    1. Remova a adição CREATE PRIVATE e substitua-a por uma adição ABSTRACT.

    2. Certifique-se de que seu código tenha a seguinte aparência:

      ABAP
      12
      * CLASS lcl_flight DEFINITION CREATE PRIVATE. CLASS lcl_flight DEFINITION ABSTRACT.
  3. Deixe a classe local LCL_PASSENGER_FLIGHT herdar da classe local LCL_FLIGHT.

    1. Role para baixo até a parte de definição da classe local LCL_PASSENGER_FLIGHT.

    2. Ajuste o código da seguinte forma:

      ABAP
      12
      CLASS lcl_passenger_flight DEFINITION INHERITING FROM lcl_flight.
  4. Corrija os erros de sintaxe "No método do construtor, os atributos de instância … só podem ser acessados após o construtor da classe superior … ser chamado." adicionando super->constructor( ). no início da implementação do método CONSTRUCTOR na subclasse LCL_PASSENGER_FLIGHT.

    Nota

    Teremos uma visão mais detalhada da lógica do construtor mais tarde neste exercício.
    1. Ajuste o código da seguinte forma:

      ABAP
      12
      METHOD constructor. super->constructor( ).
  5. Utilize uma correção rápida para mover ("puxar para cima") os seguintes componentes públicos da subclasse LCL_PASSENGER_FLIGHT para a classe superior LCL_FLIGHT:

    • Atributo carrier_id
    • connection_id do atributo
    • Atributo flight_date
    • Tipo de estrutura ST_CONNECTION_DETAILS
    • Método GET_CONNECTION_DETAILS

    Nota

    Esta etapa leva a um erro de sintaxe na implementação do método GET_CONNECTION_DETAILS movido, porque acessa um componente que ainda não está disponível na classe superior LCL_FLIGHT. Este erro será corrigido na próxima etapa.
    1. Na parte de definição da classe local LCL_PASSENGER_FLIGHT, posicione o cursor em carrier_id e selecione Ctrl + 1 para exibir uma lista de soluções rápidas disponíveis.

    2. Na lista de soluções rápidas disponíveis, selecione Pull-Up carrier_id para a classe superior lcl_flight.

    3. Repita isso para os outros componentes listados acima.

    4. A parte de definição da classe superior LCL_FLIGHT deve ter o seguinte aspecto:

      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. Utilize uma correção rápida para mover ("puxar para cima") os seguintes componentes privados da subclasse LCL_PASSENGER_FLIGHT para a classe superior LCL_FLIGHT:

    • Tipo de plano de atributo
    • Connection_details do atributo
    1. Na parte de definição da classe local LCL_PASSENGER_FLIGHT, posicione o cursor em planetype e selecione Ctrl + 1 para exibir uma lista de soluções rápidas disponíveis.

    2. Na lista de soluções rápidas disponíveis, selecione Pull-Up planetype para a classe superior lcl_flight.

    3. Repita isso para o atributo connection_details.

    4. A parte de definição da classe superior LCL_FLIGHT deve ter o seguinte aspecto:

      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. Deixe a classe local LCL_CARGO_FLIGHT herdar da classe local LCL_FLIGHT.

    1. Role até a parte de definição da classe local LCL_CARGO_FLIGHT.

    2. Ajuste o código da seguinte forma:

      ABAP
      12
      CLASS lcl_cargo_flight DEFINITION INHERITING FROM lcl_flight.
  8. Comente ou remova as definições redundantes da classe local LCL_CARGO_FLIGHT.

    Dica

    Utilize os erros de sintaxe na visão Problemas para navegar para as definições redundantes.
    1. Na visão Problemas, erro de sintaxe de clique duplo Já existe um tipo chamado "ST_CONNECTION_DETAILS".

    2. Remova ou comente a definição do tipo de estrutura ST_CONNECTION_DETAILS na classe local LCL_CARGO_FLIGHT.

    3. Repita isso para os outros componentes que já estão definidos na classe superior LCL_FLIGHT.

    Nota

    Não se esqueça de remover ou comentar também a implementação do método GET_CONNECTION_DETAILS.
  9. Corrija os erros de sintaxe "No método do construtor, os atributos de instância … só podem ser acessados após o construtor da classe superior … ser chamado." adicionando super->constructor( ). no início da implementação do método CONSTRUCTOR na subclasse LCL_CARGO_FLIGHT.

    1. Ajuste o código da seguinte forma:

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

Tarefa 3: Redefinir um método

Defina um método GET_DESCRIPTION na classe superior e redefina o mesmo nas subclasses. Mova as partes comuns da implementação para a classe superior e mantenha as partes específicas nas subclasses.

Etapas

  1. Na classe superior LCL_FLIGHT, defina um método de instância pública GET_DESCRIPTION com os mesmos parâmetros que nas subclasses.

    Dica

    Copie a definição de método de uma das subclasses.
    1. Ajuste o código da seguinte forma:

      ABAP
      123456
      CLASS lcl_flight DEFINITION ABSTRACT. PUBLIC SECTION. METHODS get_description RETURNING VALUE(r_result) TYPE string_table.
  2. Nas classes locais LCL_PASSENGER_FLIGHT e LCL_CARGO_FLIGHT, substitua as definições do método GET_DESCRIPTION por redefinições.

    Dica

    Utilize os erros de sintaxe na visão Problemas para navegar para as definições de método.
    1. Na parte de definição das duas subclasses, ajuste o código da seguinte forma:

      ABAP
      1234
      * METHODS get_description * RETURNING * VALUE(r_result) TYPE string_table. METHODS get_description REDEFINITION.
  3. Utilize uma correção rápida para adicionar uma implementação vazia para o novo método GET_DESCRIPTION à classe local LCL_FLIGHT.

    1. Na definição da classe local LCL_FLIGHT, posicione o cursor em get_description e pressione Ctrl + 1 para chamar as soluções rápidas disponíveis. Em alternativa, você pode selecionar o ícone de erro com a lâmpada no lado esquerdo do código.

    2. Na lista de sugestões, selecione Adicionar implementação para get_description.

  4. Na classe local LCL_PASSENGER_FLIGHT, ajuste a implementação do método GET_DESCRIPTION. No início da implementação, chame a implementação da classe superior e armazene o resultado no parâmetro r_result.

    1. Adicione o seguinte código:

      ABAP
      1
      r_result = super->get_description( ).
  5. Mova o código que trata dos valores VENDIDO dos seguintes atributos herdados da subclasse LCL_PASSENGER_FLIGHT para a implementação do método GET_DESCRIPTION na classe superior LCL_FLIGHT: carrier_id, connection_id, flight_date, connection_details-airport_from_id, connection_details-airport_to_id e planetype

    1. Destaque a declaração e preparação da variável local txt, bem como as duas instruções APPEND para a variável txt e o atributo planetype, e pressione Ctrl + C para copiar o snippet de código para o clipboard.

    2. Pressione Ctrl + < para adicionar um sinal de comentário no início das linhas de código selecionadas.

    3. Mude para a implementação do método GET_DESCRIPTION na classe local LCL_FLIGHT, posicione o cursor entre as instruções METHOD … e ENDMETHOD e pressione Ctrl + V para inserir o snippet de código.

    4. A implementação na classe superior deve ter o seguinte aspecto:

      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. Na classe local LCL_CARGO_FLIGHT, ajuste a implementação do método GET_DESCRIPTION correspondentemente: chame a implementação herdada do método GET_DESCRIPTION e remova ou comente as instruções APPEND redundantes.

    1. Ajuste o código da seguinte forma:

      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.

Tarefa 4: Adicionar um construtor comum

Na classe superior LCL_FLIGHT, defina um construtor de instância com os parâmetros de entrada que os dois construtores de subclasse têm em comum. Ajuste a chamada do construtor de classe superior nas subclasses para que elas encaminhem os parâmetros comuns. Em seguida, mova as partes comuns da lógica do construtor dos construtores da subclasse para o construtor da classe superior.

Etapas

  1. Na classe superior LCL_FLIGHT, defina um método CONSTRUCTOR com os mesmos parâmetros de entrada que o CONSTRUCTOR da subclasse LCL_PASSENGER_FLIGHT.

    Dica

    Não há uma solução rápida pull-up para métodos de construtor de instância. Em vez disso, copie e cole a definição de método da subclasse para a classe superior.
    1. Role até a parte de definição da classe local LCL_PASSENGER_FLIGHT.

    2. Selecione a instrução METHODS completa para o método CONSTRUCTOR e pressione Ctrl + C para copiar o snippet de código para o clipboard.

    3. Role para cima até a parte de definição da classe local LCL_FLIGHT, posicione o cursor após a instrução PUBLIC SECTION e pressione Ctrl + V para inserir o snippet de código do clipboard.

  2. Ajuste a chamada do construtor de classe superior nas subclasses. Encaminhe os parâmetros de importação para o construtor de classe superior.

    Dica

    Utilize os erros de sintaxe na visão Problemas para navegar para as chamadas do construtor de classe superior.
    1. Nos dois construtores de subclasse, ajuste o código da seguinte forma:

      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. Utilize uma correção rápida para adicionar uma implementação vazia para o construtor de classe superior.

    1. Na definição da classe local LCL_FLIGHT, posicione o cursor em constructor e pressione Ctrl + 1 para chamar as soluções rápidas disponíveis.

    2. Na lista de sugestões, selecione Adicionar implementação para construtor.

  4. Desloque as avaliações dos atributos herdados carrier_id, connection_id e flight_date dos construtores de subclasse para o construtor de classe superior.

    1. Navegue para a implementação do método CONSTRUCTOR na classe local LCL_PASSENGER_FLIGHT.

    1. Selecione as atribuições de valor para os atributos herdados carrier_id, connection_id e flight_date e pressione Ctrl + C para copiar o snippet de código para o clipboard.

    2. Pressione Ctrl + < para adicionar um sinal de comentário no início das linhas de código selecionadas.

    3. Mude para a implementação do método CONSTRUCTOR na classe local LCL_FLIGHT, posicione o cursor entre METHOD … e ENDMETHOD e pressione Ctrl + V para inserir o snippet de código.

    4. A implementação na classe superior deve ter o seguinte aspecto:

      ABAP
      12345
      METHOD constructor. me->carrier_id = i_carrier_id. me->connection_id = i_connection_id. me->flight_date = i_flight_date. ENDMETHOD.
    5. Mude para a implementação do método CONSTRUCTOR na classe local LCL_CARGO_FLIGHT e remova ou comente as avaliações redundantes.

  5. Ative e teste sua classe global como aplicativo de console. Depurar a instanciação da classe local LCL_PASSENGER_FLIGHT e a chamada do método GET_DESCRIPTION.

    1. Pressione Ctrl + F3.

    2. Pressione F9.