Pergunta

O que é herança (inheritance)?

Resposta

A herança (inheritance) é uma técnica onde uma classe passa a utilizar atributos e operações definidas em uma outra classe especificada como sua ancestral. Representa o mais importante mecanismo decorrente do polimorfismo, daí seu tratamento em destaque por qualquer linguagem de programação orientada à objetos.

A herança permite realizar o compartilhamento de atributos e operações entre classes relacionadas hierarquicamente, ou seja, uma classe tomada como origem contêm definições que podem ser utilizadas nas classes definidas como derivadas. A classe de origem é denominada classe base (base class) ou superclasse (superclass) ou classe pai enquanto as obtidas desta forma de relacionamento são chamadas de classes derivadas (derived classes) ou subclasses (subclasses) ou classes filho. A construção de classes baseadas em herança também é conhecida como subclassing.

A existência de uma relação do tipo herança pode ser facilmente identificada através da relação "é um" entre classes ("is a" relationship): uma bola de futebol de salão é uma bola de futebol que por sua vez é uma bola. Uma sentença é uma parte de um parágrafo que é uma parte de um documento. Inúmeros outros exemplos poderiam ser dados. A descoberta de relações do tipo "é um" é a chave para determinarmos quando novas classes devem ser ou não derivadas de outras existentes.

Em Java indicamos que uma classe é derivada de uma outra classe utilizando a palavra reservada extends conforme o trecho simplificado de código dado a seguir: A superclasse não recebe qualquer indicação especial.

// SuperClass.java
public class SuperClass {
  :
}

// SubClass.java
public class SubClass extends SuperClass {
  :
}

Em princípio, todos atributos e operações definidos para uma certa classe base são aplicáveis para seus descendentes que, por sua vez, não podem omitir ou suprimir tais caraterísticas pois não seriam verdadeiros descendentes se fizessem isto. Por outro lado uma subclasse pode modificar a implementação de alguma operação (reimplementar) por questões de eficiência sem modificar a interface externa da classe. Além disso as subclasses podem adicionar novos métodos e atributos não existentes na classe base, criando uma versão mais específica da classe base, isto é, especializando-a. Note que os atributos e operações adicionados em uma dada classe base não são indicados explicitamente na classe derivada mas implicitamente pela relação de herança.

Todos os atributos e operações especificadas como públicas (public) poderão ser usadas tanto pelas instâncias da classe como pelas suas classes derivadas e pelas instâncias das classes derivadas. Diferentemente, atributos e operações especificados como protegidos (protected) só poderão ser utilizadas pelas classes derivadas mas não por instâncias de qualquer nível. Finalmente tudo aquilo definido como privado (private) não poderá ser utilizado externamente a classe, nem por classes derivadas nem por instâncias de qualquer nível.

Usualmente a herança é utilizada em projetos mais amplos e organizados onde se define uma classe em termos mais genéricos ou amplos sendo que tal classe é depois refinada sucessivamente em uma ou mais subclasses específicas. Daí o origem do termo técnico que descreve a herança: especialização (specialization) pois uma dada subclasse possui tudo aquilo definido pela sua superclasse além de atributos e operações localmente adicionados.

Por outro lado a herança oferece um mecanismo para a generalização pois uma instância de uma classe é uma instância de todos os ancestrais desta classe, isto é, um objeto de uma classe derivada pode ser tratado polimorficamente como um objeto da superclasse.

No mundo real alguns objetos e classes podem ser descritos como casos especiais, especializações ou generalizações de outros objetos e classes. Por exemplo, a bola de futebol de salão é uma especialização da classe bola de futebol que por sua vez é uma especialização da classe bola. Aquilo que foi descrito para uma certa classe não precisa ser repetido para uma classe mais especializada originada na primeira.

Como os atributos e operações definidos na classe base não precisam ser repetidos numa classe derivada, a orientação à objetos auxilia a reduzir a repetição de código dentro de um programa ao mesmo tempo que possibilita que classes mais genéricas sejam reaproveitadas em outros projetos (reusabilidade de código). Outro aspecto bastante importante é que se o projeto de uma hierarquia de classe é suficientemente genérico e amplo temos o desenvolvimento de uma solução generalizada e com isto torna-se possível mais do que a reutilização de código, mas passa a ser possível o que denomina reutilização do projeto. Uma classe ou hierarquia de classes que pode ser genericamente utilizada em outros projetos é que se chama de padrão de projeto ou design pattern.