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.



