Usando a palavra-chave final com herança em Java

Enquanto um dos Java's pontos fortes é o conceito de herança, no qual classe pode derivar de outra, às vezes é desejável impedir a herança de outra classe. Para impedir a herança, use a palavra-chave "final" ao criar a classe.

Por exemplo, se é provável que uma classe seja usada por outros programadores, você pode impedir a herança se alguma subclasse criada puder causar problemas. Um exemplo típico é o Classe String. Se quisermos criar uma subclasse String:

classe pública MyString estende String {
}

Seríamos confrontados com este erro:

 não pode herdar do java.lang final. Corda 

Os designers da classe String perceberam que não era um candidato à herança e impediram que ela fosse estendida.

Por que impedir a herança?

A principal razão para impedir herança é garantir que o comportamento de uma classe não seja corrompido por uma subclasse.

Suponha que tenhamos uma classe Account e uma subclasse que a estenda, OverdraftAccount. A conta de classe possui um método getBalance ():

 public double getBalance ()

{

 retorne this.balance;

 } 

instagram viewer

Neste ponto de nossa discussão, a subclasse OverdraftAccount não substituiu esse método.

(Nota: Para outra discussão usando essas classes Account e OverdraftAccount, veja como um subclasse pode ser tratada como uma superclasse).

Vamos criar uma instância para cada uma das classes Account e OverdraftAccount:

 Conta bobsAccount = nova conta (10);

 bobsAccount.depositMoney (50);

 OverdraftAccount jimsAccount = new OverdraftAccount (15.05.500,0.05);

 jimsAccount.depositMoney (50);

 // cria uma matriz de objetos de conta

 // podemos incluir jimsAccount porque 

 // só quer tratá-lo como um objeto de conta

 Conta [] contas = {bobsAccount, jimsAccount};


 // para cada conta na matriz, exiba o saldo

 para (Conta a: contas)

 {

 System.out.printf ("O saldo é% .2f% n", a.getBalance ());

 }

 A saída é:

 O saldo é 60,00

 O saldo é de 65,05 

Tudo parece funcionar como esperado, aqui. Mas e se OverdraftAccount substituir o método getBalance ()? Não há nada para impedi-lo de fazer algo assim:

 public class OverdraftAccount estende a conta {


 private double overdraftLimit;

 private double overdraftFee;


 // o restante da definição de classe não está incluída


 public double getBalance ()

 {

 retorno 25,00;

 }

 } 

Se o código de exemplo acima for executado novamente, a saída será diferente porque o comportamento do getBalance () na classe OverdraftAccount é chamado para jimsAccount:

 A saída é:

 O saldo é 60,00

 O saldo é de 25,00 

Infelizmente, a subclasse OverdraftAccount será Nunca forneça o saldo correto porque corrompemos o comportamento da classe Account por herança.

Se você projetar uma classe para ser usada por outros programadores, sempre considere as implicações de qualquer subclasse em potencial. É por isso que a classe String não pode ser estendida. É extremamente importante que os programadores saibam que, quando criam um objeto String, ele sempre se comporta como um String.

Como impedir a herança

Para impedir que uma classe seja estendida, a declaração de classe deve dizer explicitamente que não pode ser herdada. Isso é alcançado usando a palavra-chave "final":

 conta pública de classe final {


 } 

Isso significa que a classe Account não pode ser uma superclasse e a classe OverdraftAccount não pode mais ser sua subclasse.

Às vezes, você pode limitar apenas certos comportamentos de uma superclasse para evitar a corrupção de uma subclasse. Por exemplo, OverdraftAccount ainda pode ser uma subclasse de Account, mas deve ser impedido de substituir o método getBalance ().

Nesse caso, use a palavra-chave "final" na declaração do método:

 conta de classe pública {


 saldo duplo privado;


 // o restante da definição de classe não está incluída


 público final duplo getBalance ()

 {

 retorne this.balance;

 } 

 } 

Observe como a palavra-chave final não é usada na definição de classe. É possível criar subclasses de conta, mas não podem mais substituir o método getBalance (). Qualquer código que chame esse método pode ter certeza de que funcionará como o programador original pretendia.