Recentemente, comecei a analisar o desenvolvimento do Android. Isso me trouxe de volta ao mundo do desenvolvimento de software Java. A última vez que trabalhei com Java, admito, não entendi OOP tanto quanto (acho) agora.
Tendo usado principalmente o C # em minha carreira, percebo uma diferença surpreendente em como a herança é usada Java e C #.
Em C #, parecia que a herança poderia ser evitada na maioria das situações. A tarefa em questão geralmente pode ser realizada usando classes concretas da estrutura .NET .
Em Java, pelo que estou coletando de amostras de código, parece que a estrutura Java fornece muitas interfaces ou classes abstratas que devem ser implementadas / estendidas pelo desenvolvedor.
Parece ser uma diferença muito grande para se resumir ao estilo. Qual é o raciocínio por trás disso? Sinto que não vou escrever código Java limpo até entender isso.
Além disso, isso é limitado apenas ao SDK do Android ou é uma abordagem de OOP em todo o Java?
Ou, de outra forma,
O que há no design dessas duas linguagens que (parece encorajar) mais ou menos o uso de herança do que a outra?
Se as linguagens tratam a herança de forma idêntica, e assumindo que minha observação é válida, significa que isso está relacionado ao design das estruturas / bibliotecas e não às linguagens. Qual seria a motivação para esse tipo de design?
fonte
Respostas:
Meu entendimento é que, em grande parte, é simplesmente uma decisão estilística. Bem, talvez não seja estilo, mas os idiomas da linguagem / ambiente. Os desenvolvedores de bibliotecas padrão do Java seguiram um conjunto de diretrizes de design e os desenvolvedores do .NET outro (apesar de terem a capacidade de ver como a abordagem do Java funcionava).
Há muito pouco nas línguas atuais para incentivar ou dissuadir a herança. Apenas duas coisas me parecem relevantes:
O .NET introduziu os genéricos mais cedo, antes de implementar muito código não genérico. A alternativa é muita herança para digitar coisas especializadas.
Uma mudança maior foi que o .NET deu suporte a delegados. Em Java, você está preso à herança (anônima) para fornecer a funcionalidade mais básica das variáveis. Isso leva a uma diferença relativamente grande na maneira como o código é projetado para tirar proveito dos delegados ou para evitar as estruturas estranhas de herança necessárias para fazê-lo em Java.
fonte
Estes são idiomas muito diferentes, especialmente nesta área. Digamos que você tenha uma aula. Nesse caso, tornaremos um controle de usuário, algo como uma caixa de texto. Chame de UIControl. Agora queremos colocar isso em outra classe. Nesse caso, como estamos usando uma interface do usuário para o nosso exemplo, a chamaremos de classe CleverPanel. Nossa instância CleverPanel vai querer saber sobre o que está acontecendo com sua instância UIControl por vários motivos. Como fazer isso?
Em C #, a abordagem básica é verificar vários eventos, configurando métodos que serão executados quando cada evento interessante for acionado. Em Java, que não possui eventos, a solução usual é passar um objeto com vários métodos de manipulação de "eventos" para um método UIControl:
Até agora, a diferença entre C # e Java não é profunda. No entanto, temos a interface DoSomething que não é necessária em C #. Além disso, essa interface pode incluir muitos métodos que não são necessários na maioria das vezes. Em C #, simplesmente não lidamos com esse evento. Em Java, criamos uma classe que fornece uma implementação nula para todos os métodos de interface, DoSomethingAdapter. Agora substituímos DoSomething por DoSomethingAdapter e não precisamos escrever nenhum método para uma compilação limpa. Acabamos substituindo os métodos necessários para que o programa funcione corretamente. Então, acabamos precisando de uma interface e usando herança em Java para corresponder ao que fizemos com os eventos em C #.
Este é um exemplo, não uma discussão abrangente, mas fornece os fundamentos do motivo pelo qual há tanta herança em Java em vez de C #.
Agora, por que o Java funciona dessa maneira? Flexibilidade. O objeto passado para whenSomethingHappens poderia ter sido passado para o CleverPanel de outro lugar completamente. Pode ser algo que várias instâncias do CleverPanel devem passar para seus objetos do tipo UIControl para ajudar um objeto do CleverWindow em algum lugar. Ou o UIControl poderia entregá-lo a um de seus componentes.
Além disso, em vez de um adaptador, pode haver uma implementação DoSomething em algum lugar que tenha milhares de linhas de código por trás. Nós poderíamos criar uma nova instância disso e passá-la. Talvez seja necessário substituir um método. Um truque comum em Java é ter uma classe grande com um método como:
Então, no CleverlPanel:
A plataforma Java de código-fonte aberto faz muito disso, o que tende a pressionar os programadores a fazerem mais - tanto porque eles o seguem como um exemplo e simplesmente para usá-lo. Eu acho que o design básico da linguagem está por trás do design da estrutura da Sun e por trás dos programadores Java que usam as técnicas quando não estão usando a estrutura.
É muito fácil criar uma classe em tempo real em Java. A classe, anônima ou nomeada, só precisa ser referenciada em um pequeno bloco de código enterrado profundamente em um método. Ele pode ser criado completamente novo ou com pequenas modificações em uma classe existente muito grande. (E a classe existente pode ser de nível superior em seu próprio arquivo, ou aninhada em uma classe de nível superior, ou definida apenas dentro de um único bloco de código). A nova instância de classe pode ter acesso total a todos os dados do objeto de criação. E a nova instância pode ser transmitida e usada em todo o programa, representando o objeto que o criou.
(Como um aparte, observe que um grande uso de herança aqui - como em outros lugares em Java - é simplesmente para fins DRY. Permite que diferentes classes reutilizem o mesmo código. Observe também a facilidade de herança em Java que incentiva isso. )
Novamente, esta não é uma discussão abrangente; Estou apenas arranhando a superfície aqui. Mas sim, há uma diferença surpreendente em como a herança é usada entre Java e C #. Eles são, nesse sentido, idiomas muito diferentes. Não é sua imaginação.
fonte
Não há absolutamente nenhuma diferença na maneira como a herança é tratada entre Java e C #. Quando você realmente usará herança ou composição é definitivamente uma decisão de design e de maneira alguma é algo que Java ou C # incentiva ou desencoraja. Eu gostaria de sugerir a leitura deste artigo .
Espero ter ajudado!
fonte