Espero que não seja muito acadêmico ...
Digamos que eu precise de números reais e complexos na minha biblioteca de SW.
Com base no relacionamento is-a (ou aqui ), o número real é um número complexo, onde b na parte imaginária do número complexo é simplesmente 0.
Por outro lado, minha implementação seria que esse filho estende o pai, portanto, no pai RealNumber, eu teria uma parte real e o filho ComplexNumber acrescentaria arte imaginária.
Também há uma opinião de que herança é má .
Lembro-me como ontem, quando eu estava aprendendo POO na universidade, disse meu professor, este não é um bom exemplo de herança, já que o valor absoluto desses dois é calculado de maneira diferente (mas para isso temos método de sobrecarga / polimorfismo, certo?) .. .
Minha experiência é que muitas vezes usamos herança para resolver DRY, como resultado, muitas vezes temos classes abstratas artificiais na hierarquia (muitas vezes temos problemas para encontrar nomes, pois eles não representam objetos do mundo real).
fonte
Respostas:
Mesmo que, em um sentido matemático, um número real seja um número complexo, não é uma boa idéia derivar real do complexo. Ele viola o Princípio de Substituição de Liskov dizendo (entre outras coisas) que uma classe derivada não deve ocultar propriedades de uma classe base.
Nesse caso, um número real teria que ocultar a parte imaginária do número complexo. É claro que não faz sentido armazenar um número de ponto flutuante oculto (parte imaginária) se você precisar apenas da parte real.
Esse é basicamente o mesmo problema que o exemplo de retângulo / quadrado mencionado em um comentário.
fonte
Esta não é realmente uma razão convincente contra todas as heranças aqui, apenas o modelo
class RealNumber
<-> propostoclass ComplexNumber
.Você pode razoavelmente definir uma interface
Number
, que tantoRealNumber
eComplexNumber
iria implementar.Isso pode parecer
Mas, então, você deseja restringir os outros
Number
parâmetros nessas operações para serem do mesmo tipo derivadothis
, com o qual você pode se aproximarOu então, você usaria uma linguagem que permitisse polimorfismo estrutural, em vez de polimorfismo de subtipo. Para o caso específico de números, talvez você precise da capacidade de sobrecarregar operadores aritméticos.
fonte
Solução: Não tem
RealNumber
classe públicaEu acharia totalmente aceitável se
ComplexNumber
tivesse um método estático de fábricafromDouble(double)
que retornasse um número complexo com o imaginário sendo zero. Você pode usar todas as operações que usaria em umaRealNumber
instância nessaComplexNumber
instância.Mas tenho problemas para entender por que você deseja / precisa ter uma
RealNumber
classe pública herdada . Geralmente, a herança é usada por esses motivos (fora da minha cabeça, me corrija se faltou alguma)estendendo o comportamento.
RealNumbers
não pode fazer operações extras que um número complexo não possa fazer, portanto, não faz sentido.implementar comportamento abstrato com uma implementação específica. Como
ComplexNumber
não deve ser abstrato, isso também não se aplica.reutilização de código. Se você apenas usa a
ComplexNumber
classe, reutiliza 100% do código.implementação mais específica / eficiente / precisa para uma tarefa específica. Isso poderia ser aplicado aqui,
RealNumbers
poderia implementar algumas funcionalidades mais rapidamente. Mas essa subclasse deve estar oculta por trás da estáticafromDouble(double)
e não deve ser conhecida do lado de fora. Dessa forma, não seria necessário ocultar a parte imaginária. Para o exterior, deve haver apenas números complexos (quais são os números reais). Você também pode retornar essa classe RealNumber privada de qualquer operação na classe numérica complexa que resulte em um número real. (Isso pressupõe que as classes são imutáveis como a maioria das classes numéricas.)É como implementar uma subclasse de Inteiro chamada Zero e codificar algumas das operações, pois elas são triviais para zero. Você pode fazer isso, pois todo zero é um número inteiro, mas não o torne público, oculte-o atrás de um método de fábrica.
fonte
Dizer que um número real é um número complexo tem mais significado na matemática, especialmente na teoria dos conjuntos, do que na ciência da computação.
Em matemática, dizemos:
No entanto, isso não significa que você deva usar a herança ao projetar sua biblioteca para incluir uma classe RealNumber e ComplexNumber. Em Java eficaz, segunda edição por Joshua Bloch; O item 16 é "Favorecer a composição sobre a herança". Para evitar os problemas mencionados nesse item, depois de definir sua classe RealNumber, ela poderá ser usada na sua classe ComplexNumber:
Isso permite que você reutilize sua classe RealNumber para manter seu código SECO, evitando os problemas identificados por Joshua Bloch.
fonte
Há duas questões aqui. A primeira é que é comum usar os mesmos termos para os tipos de contêineres e os tipos de seu conteúdo, especialmente com tipos primitivos como números. O termo
double
, por exemplo, é usado para descrever um valor de ponto flutuante de precisão dupla e um contêiner no qual um pode ser armazenado.A segunda questão é que, embora seja - um relacionamento entre contêineres a partir do qual vários tipos de objetos podem ser lidos se comporte da mesma maneira que os relacionamentos entre os próprios objetos, aqueles entre contêineres nos quais vários tipos de objetos podem ser colocados se comportam opostos aos de seu conteúdo . Toda gaiola que é conhecida por conter uma instância de
Cat
será uma gaiola que contém uma instância deAnimal
, mas não precisa ser uma gaiola que contém uma instância deSiameseCat
. Por outro lado, toda gaiola que pode conter todas as instâncias deCat
será uma gaiola que pode conter todas as instâncias deSiameseCat
, mas não precisa ser uma gaiola que possa conter todas as instâncias deAnimal
. O único tipo de gaiola que pode conter todas as instânciasCat
e pode ser garantido nunca contém outra coisa senão uma instância deCat
, é uma gaiola deCat
. Qualquer outro tipo de gaiola seria incapaz de aceitar algumas instânciasCat
daquilo que deveria aceitar ou seria capaz de aceitar coisas que não são instânciasCat
.fonte