Quais são as boas razões para proibir a herança em Java, por exemplo, usando classes finais ou classes usando um único construtor privado sem parâmetros? Quais são as boas razões para tornar um método final?
Quais são as boas razões para proibir a herança em Java, por exemplo, usando classes finais ou classes usando um único construtor privado sem parâmetros? Quais são as boas razões para tornar um método final?
Respostas:
Sua melhor referência aqui é o item 19 do excelente livro de Joshua Bloch, "Effective Java", chamado "Design e documento para herança, ou então a proíbe". (É o item 17 da segunda edição e o item 15 da primeira edição.) Você realmente deve lê-lo, mas vou resumir.
A interação de classes herdadas com seus pais pode ser surpreendente e imprevisível se o ancestral não foi projetado para ser herdado.
As aulas devem, portanto, ser de dois tipos:
Classes projetadas para serem estendidas e com documentação suficiente para descrever como isso deve ser feito
Classes marcadas como finais
Se você estiver escrevendo código puramente interno, pode ser um pouco exagerado. No entanto, o esforço extra envolvido na adição de cinco caracteres a um arquivo de classe é muito pequeno. Se você está escrevendo apenas para consumo interno, um codificador futuro sempre pode remover o 'final' - você pode pensar nele como um aviso dizendo "esta classe não foi projetada com a herança em mente".
Convém finalizar um método para que as classes substituintes não possam alterar o comportamento que é contado em outros métodos. Os métodos chamados nos construtores geralmente são declarados finais, para que você não tenha surpresas desagradáveis ao criar objetos.
final
.
Um motivo para finalizar uma aula seria se você quisesse forçar a composição sobre a herança. Isso geralmente é desejável para evitar um acoplamento rígido entre as classes.
Existem 3 casos de uso em que você pode usar os métodos finais.
Objetivo de finalizar uma aula:
Para que nenhum corpo possa estender essas classes e mudar seu comportamento.
Por exemplo: classe Wrapper Integer é uma classe final. Se essa classe não for final, qualquer um poderá estender o Inteiro para sua própria classe e alterar o comportamento básico da classe inteira. Para evitar isso, o java criou todas as classes de wrapper como classes finais.
DerivedInteger
, ela ainda não altera a classe Integer original, e quem usa usa DerivedInteger
por sua conta e risco, por isso ainda não entendo por que é um problema.
convém criar objetos imutáveis ( http://en.wikipedia.org/wiki/Immutable_object ), criar um singleton ( http://en.wikipedia.org/wiki/Singleton_pattern ) ou desejar impedir que alguém substitua o método por razões de eficiência ou segurança.
A herança é como uma serra elétrica - muito poderosa, mas terrível nas mãos erradas. Você cria uma classe a ser herdada (o que pode limitar a flexibilidade e levar muito mais tempo) ou deve proibi-la.
Consulte os itens 16 e 17 da Java Effective 2nd 2nd, ou minha postagem no blog "Imposto sobre herança" .
Hmmm ... eu posso pensar em duas coisas:
Você pode ter uma classe que lida com certos problemas de segurança. Subclassificando-o e alimentando o sistema com a versão subclassificada, um invasor pode contornar as restrições de segurança. Por exemplo, seu aplicativo pode suportar plug-ins e, se um plug-in puder apenas subclassificar suas classes relevantes de segurança, ele poderá usar esse truque para, de alguma forma, contrabandear uma versão subclassificada dele no lugar. No entanto, isso é algo que a Sun precisa lidar com applets e similares, talvez não seja um caso tão realista.
Muito mais realista é evitar que um objeto se torne mutável. Por exemplo, como as Strings são imutáveis, seu código pode manter com segurança referências a ele
String blah = someOtherString;
em vez de copiar a string primeiro. No entanto, se você puder subclassificar String, poderá adicionar métodos que permitam que o valor da string seja modificado, agora nenhum código poderá confiar mais que a string permanecerá a mesma se apenas copiar a string como acima, em vez disso, deverá duplicar o valor corda.
Além disso, se você estiver escrevendo uma classe comercial de código fechado, talvez não queira que as pessoas alterem a funcionalidade na linha, especialmente se você precisar dar suporte a ela e as pessoas tiverem substituído seu método e se queixarem de que a chamada resultados inesperados.
Se você marcar classes e métodos como final, poderá notar um pequeno ganho de desempenho, pois o tempo de execução não precisa procurar o método de classe correto para chamar um determinado objeto. Os métodos não finais são marcados como virtuais, para que possam ser estendidos adequadamente, se necessário, e os métodos finais podem ser diretamente vinculados ou compilados na linha.
Impedir que as pessoas façam coisas que possam confundir a si mesmas e aos outros. Imagine uma biblioteca de física onde você tenha algumas constantes ou cálculos definidos. Sem usar a palavra-chave final, alguém poderia aparecer e redefinir os cálculos básicos ou constantes que NUNCA deveriam mudar.
Você deseja finalizar um método para que a substituição de classes não mude seu comportamento. Quando você quiser alterar o comportamento, torne o método público. Quando você substitui um método público, ele pode ser alterado.