Eu sei que herança múltipla não é permitida em Java e C #. Muitos livros apenas dizem que a herança múltipla não é permitida. Mas pode ser implementado usando interfaces. Nada é discutido sobre por que não é permitido. Alguém pode me dizer exatamente por que não é permitido?
c#
java
language-design
multiple-inheritance
Abdulsattar Mohammed
fonte
fonte
Respostas:
A resposta curta é: porque os designers da linguagem decidiram não fazê-lo.
Basicamente, parecia que os designers .NET e Java não permitiam herança múltipla porque eles argumentaram que adicionar MI acrescentava muita complexidade às linguagens, ao mesmo tempo que proporcionava muito pouco benefício .
Para uma leitura mais divertida e aprofundada, existem alguns artigos disponíveis na web com entrevistas de alguns dos designers da linguagem. Por exemplo, para .NET, Chris Brumme (que trabalhou na MS no CLR) explicou as razões pelas quais eles decidiram não:
Você pode ler o artigo completo aqui.
Para Java, você pode ler este artigo :
fonte
A herança múltipla de implementação é o que não é permitido.
O problema é que o compilador / tempo de execução não consegue descobrir o que fazer se você tiver uma classe Cowboy e uma classe Artist, ambas com implementações para o método draw (), e então tentar criar um novo tipo CowboyArtist. O que acontece quando você chama o método draw ()? Alguém está morto na rua ou você tem uma linda aquarela?
Eu acredito que é chamado de problema de herança de diamante duplo.
fonte
Motivo: Java é muito popular e fácil de codificar, devido à sua simplicidade.
Portanto, o que quer que os desenvolvedores java pareçam difíceis e complicados de entender para os programadores, eles tentam evitar. Um desses tipos de propriedade é a herança múltipla.
Problema com herança múltipla: problema do diamante.
Exemplo :
Esta é a ambigüidade existente no problema do diamante.
Não é impossível resolver este problema, mas cria mais confusão e complexidades para o programador durante a leitura. Isso causa mais problemas do que tenta resolver.
Nota : Mas de qualquer maneira, você sempre pode implementar herança múltipla indiretamente usando interfaces.
fonte
Porque Java tem uma filosofia de design muito diferente do C ++. (Não vou discutir C # aqui.)
Ao projetar C ++, Stroustrup queria incluir recursos úteis, independentemente de como eles poderiam ser mal utilizados. É possível estragar muito com herança múltipla, sobrecarga de operador, modelos e vários outros recursos, mas também é possível fazer algumas coisas muito boas com eles.
A filosofia de design Java é enfatizar a segurança nas construções de linguagem. O resultado é que há coisas que são muito mais difíceis de fazer, mas você pode ter muito mais certeza de que o código que está olhando significa o que você pensa que significa.
Além disso, Java foi em grande parte uma reação de C ++ e Smalltalk, as linguagens OO mais conhecidas. Existem muitas outras linguagens OO (Common Lisp foi na verdade a primeira a ser padronizada), com diferentes sistemas OO que lidam melhor com MI.
Sem falar que é inteiramente possível fazer MI em Java, usando interfaces, composição e delegação. É mais explícito do que em C ++ e, portanto, é mais complicado de usar, mas fornecerá algo que você provavelmente entenderá à primeira vista.
Não há uma resposta certa aqui. As respostas são diferentes, e qual é a melhor para uma determinada situação depende das aplicações e da preferência individual.
fonte
A principal (embora não seja a única) razão pela qual as pessoas se afastam do MI é o chamado "problema do diamante", que leva à ambiguidade em sua implementação. Este artigo da Wikipedia discute e explica melhor do que eu poderia. O MI também pode levar a um código mais complexo, e muitos designers OO afirmam que você não precisa do MI e, se usá-lo, seu modelo provavelmente está errado. Não tenho certeza se concordo com este último ponto, mas manter as coisas simples é sempre um bom plano.
fonte
Em C ++, a herança múltipla era uma grande dor de cabeça quando usada incorretamente. Para evitar esses problemas de design populares, a "herança" de várias interfaces foi forçada em linguagens modernas (java, C #).
fonte
A herança múltipla é
Portanto, pode ser considerado uma escolha sábia não incluir a herança múltipla na linguagem Java.
fonte
Outra razão é que a herança simples torna a conversão trivial, não emitindo instruções do assembler (além de verificar a compatibilidade dos tipos quando necessário). Se você tivesse herança múltipla, precisaria descobrir onde na classe filha um determinado pai começa. Portanto, o desempenho é certamente uma vantagem (embora não seja a única).
fonte
Nos velhos tempos (anos 70), quando a Ciência da Computação era mais Ciência e menos produção em massa, os programadores tinham tempo para pensar em um bom design e boa implementação e, como resultado, os produtos (programas) tinham alta qualidade (por exemplo, design TCP / IP e implementação). Hoje em dia, quando todo mundo está programando e os gerentes estão mudando as especificações antes dos prazos, questões sutis como a descrita no link da Wikipedia da postagem de Steve Haigh são difíceis de rastrear; portanto, a "herança múltipla" é limitada pelo design do compilador. Se gostar, você ainda pode usar C ++ .... e ter toda a liberdade que quiser :)
fonte
Aceito a declaração de que "herança múltipla não é permitida em Java" com uma pitada de sal.
A herança múltipla é definida quando um "Tipo" herda de mais de um "Tipos". E as interfaces também são classificadas como tipos, pois têm comportamento. Portanto, Java tem herança múltipla. Só que é mais seguro.
fonte
O carregamento dinâmico de classes torna a implementação de herança múltipla difícil.
Na verdade, em java, eles evitavam a complexidade da herança múltipla, em vez de usar herança e interface simples. A complexidade da herança múltipla é muito alta em uma situação como explicada abaixo
problema de diamante de herança múltipla. Temos duas classes B e C herdando de A. Suponha que B e C estão substituindo um método herdado e fornecem sua própria implementação. Agora D herda de B e C fazendo herança múltipla. D deve herdar esse método sobrescrito, jvm não consegue decidir qual método sobrescrito será usado?
Em c ++ funções virtuais são usadas para manipular e temos que fazer explicitamente.
Isso pode ser evitado usando interfaces, não há corpos de método. As interfaces não podem ser instanciadas - elas só podem ser implementadas por classes ou estendidas por outras interfaces.
fonte
Na verdade, herança múltipla surgirá com a complexidade se as classes herdadas tiverem a mesma função. isto é, o compilador terá uma confusão sobre qual escolher (problema do diamante). Portanto, em Java essa complexidade foi removida e deu interface para obter a funcionalidade como herança múltipla fornecida. Podemos usar interface
fonte
Java tem conceito, ou seja, polimorfismo. Existem 2 tipos de polimorfismo em java. Há sobrecarga de método e substituição de método. Entre eles, a substituição de métodos acontece com relacionamento de super e subclasse. Se estivermos criando um objeto de uma subclasse e invocando o método da superclasse, e se a subclasse estender mais de uma classe, qual método de superclasse deve ser chamado?
Ou, ao chamar o construtor da superclasse por
super()
, qual construtor da superclasse será chamado?Essas decisões são impossíveis pelos recursos atuais da API Java. portanto, herança múltipla não é permitida em java.
fonte
A herança múltipla não é permitida em Java diretamente, mas por meio de interfaces é permitida.
Razão:
Herança múltipla: apresenta mais complexidade e ambiguidade.
Interfaces: interfaces são classes completamente abstratas em Java que fornecem uma maneira uniforme de delinear adequadamente a estrutura ou o funcionamento interno de seu programa a partir de sua interface disponível publicamente, com a consequência sendo uma maior quantidade de flexibilidade e código reutilizável, bem como mais controle sobre como você cria e interage com outras classes.
Mais precisamente, eles são uma construção especial em Java com a característica adicional que permite que você execute um tipo de herança múltipla, ou seja, classes que podem ser atualizadas para mais de uma classe.
Vamos dar um exemplo simples.
Suponha que existam 2 superclasses de classes A e B com os mesmos nomes de método, mas com funcionalidades diferentes. Por meio do seguinte código com (estende) a herança múltipla de palavra-chave não é possível.
Mas por meio de interfaces, com (implementa) a herança múltipla de palavras-chave é possível.
fonte
Você pode encontrar a resposta neste link de documentação
Se a herança múltipla for permitida e quando você criar um objeto instanciando essa classe, esse objeto herdará campos de todas as superclasses da classe. Isso causará dois problemas.
E se métodos ou construtores de superclasses diferentes instanciarem o mesmo campo?
Qual método ou construtor terá precedência?
Mesmo que a herança múltipla de estado agora seja permitida, você ainda pode implementar
Herança múltipla de tipo : capacidade de uma classe de implementar mais de uma interface.
Herança múltipla de implementação (por meio de métodos padrão em interfaces): Capacidade de herdar definições de método de várias classes
Consulte esta pergunta SE relacionada para obter informações adicionais:
Ambiguidade de herança múltipla com interface
fonte
Em C ++, uma classe pode herdar (direta ou indiretamente) de mais de uma classe, o que é conhecido como herança múltipla .
C # e Java, entretanto, limitam as classes à herança única que cada classe herda de uma única classe pai.
A herança múltipla é uma maneira útil de criar classes que combinam aspectos de duas hierarquias de classes distintas, algo que geralmente acontece ao usar diferentes estruturas de classe em um único aplicativo.
Se duas estruturas definem suas próprias classes de base para exceções, por exemplo, você pode usar herança múltipla para criar classes de exceção que podem ser usadas com qualquer estrutura.
O problema com a herança múltipla é que ela pode levar à ambiguidade. O exemplo clássico é quando uma classe herda de duas outras classes, cada uma das quais herda da mesma classe:
Neste exemplo, o
flag
membro de dados é definido porclass A
. Masclass D
descende declass B
eclass C
, de que ambos derivamA
, então, em essência, duas cópias deflag
estão disponíveis porque duas instâncias deA
estão naD
hierarquia de classes de. Qual você deseja definir? O compilador reclamará que a referência aflag
inD
é ambígua . Uma correção é eliminar a ambiguidade da referência explicitamente:Outra correção é declarar B e C como
virtual base classes
, o que significa que apenas uma cópia de A pode existir na hierarquia, eliminando qualquer ambigüidade.Outras complexidades existem com herança múltipla, como a ordem em que as classes básicas são inicializadas quando um objeto derivado é construído ou a maneira como os membros podem ser inadvertidamente ocultados das classes derivadas. Para evitar essas complexidades, algumas linguagens se restringem ao modelo mais simples de herança única.
Embora isso simplifique consideravelmente a herança, também limita sua utilidade porque apenas classes com um ancestral comum podem compartilhar comportamentos. As interfaces atenuam um pouco essa restrição, permitindo que classes em diferentes hierarquias exponham interfaces comuns, mesmo que não sejam implementadas por meio do compartilhamento de código.
fonte
Imagine este exemplo: eu tenho uma aula
Shape1
Tem
CalcualteArea
método:Há outra classe
Shape2
que também tem o mesmo métodoAgora eu tenho uma classe filha Circle, ela deriva de Shape1 e Shape2;
Agora, quando eu crio um objeto para Círculo e chamo o método, o sistema não sabe qual método de cálculo de área deve ser chamado. Ambos têm as mesmas assinaturas. Portanto, o compilador ficará confuso. É por isso que várias heranças não são permitidas.
Mas pode haver várias interfaces porque as interfaces não têm definição de método. Mesmo que ambas as interfaces tenham o mesmo método, ambas não possuem nenhuma implementação e sempre o método da classe filha será executado.
fonte