Eu li esta pergunta e pensei que seria facilmente resolvido (não que não seja solucionável sem) se alguém pudesse escrever:
@Override
public String toString() {
return super.super.toString();
}
Não tenho certeza se é útil em muitos casos, mas me pergunto por que não é e se existe algo assim em outros idiomas.
O que é que vocês acham?
Edição: Para esclarecer: sim, eu sei, isso é impossível em Java e eu realmente não sinto falta. Isso não era nada que eu esperava que funcionasse e fiquei surpreso ao receber um erro do compilador. Eu apenas tive a ideia e gostaria de discuti-la.
java
superclass
Tim Büthe
fonte
fonte
super.super.toString()
contradiz sua própria decisão quando você escolhe estender uma classe, aceitando todos (e não alguns) seus recursos.Respostas:
Viola o encapsulamento. Você não deve ignorar o comportamento da classe pai. Às vezes, faz sentido ignorar o comportamento de sua própria classe (principalmente de dentro do mesmo método), mas não o de seus pais. Por exemplo, suponha que tenhamos uma "coleção de itens" base, uma subclasse representando "uma coleção de itens vermelhos" e uma subclasse que representa "uma coleção de itens vermelhos grandes". Faz sentido ter:
Tudo bem - o RedItems sempre pode ter certeza de que os itens que ele contém estão todos vermelhos. Agora suponha que fosse capaz de chamar super.super.add ():
Agora podemos adicionar o que quisermos, e o invariante em
RedItems
é quebrada.Isso faz sentido?
fonte
Eu acho que Jon Skeet tem a resposta correta. Gostaria de acrescentar que você pode acessar variáveis sombreadas de superclasses de superclasses lançando
this
:que produz a saída:
(exemplo do JLS )
No entanto, isso não funciona para chamadas de método, porque elas são determinadas com base no tipo de tempo de execução do objeto.
fonte
Eu acho que o código a seguir permite usar super.super ... super.method () na maioria dos casos. (mesmo que seja feio fazer isso)
Em resumo
Uso:
fonte
super.super.
convida os programadores a encontrar maneiras novas, complicadas e flagrantes de dar um tiro no pé em busca de uma solução alternativa, este é um exemplo perfeito disso, porque seus colegas provavelmente o odeiam tanto por escrever algo assim eles pessoalmente e literalmente lhe darão um tiro no pé. +1Como não tenho reputação suficiente para comentar, adicionarei isso às outras respostas.
Jon Skeet responde excelentemente, com um belo exemplo. Matt B tem razão: nem todas as superclasses têm supers. Seu código seria quebrado se você chamasse um super de um super que não tivesse super.
A programação orientada a objetos (que é Java) é sobre objetos, não funções. Se você deseja programação orientada a tarefas, escolha C ++ ou outra coisa. Se o seu objeto não se encaixa na sua superclasse, é necessário adicioná-lo à "classe dos avós", criar uma nova classe ou encontrar outro super em que ele se encaixe.
Pessoalmente, achei essa limitação um dos maiores pontos fortes de Java. O código é um pouco rígido em comparação com outros idiomas que eu usei, mas eu sempre sei o que esperar. Isso ajuda com o objetivo "simples e familiar" de Java. Em minha opinião, chamar super.super não é simples ou familiar. Talvez os desenvolvedores sentissem o mesmo?
fonte
Existem algumas boas razões para fazer isso. Você pode ter uma subclasse que possui um método implementado incorretamente, mas o método pai é implementado corretamente. Por pertencer a uma biblioteca de terceiros, talvez você não consiga / não queira alterar a fonte. Nesse caso, você deseja criar uma subclasse, mas substitui um método para chamar o método super.super.
Conforme mostrado em alguns outros pôsteres, é possível fazer isso através da reflexão, mas deve ser possível fazer algo como
(SuperSuperClasse isso) .theMethod ();
Estou lidando com esse problema agora - a solução rápida é copiar e colar o método da superclasse no método da sub-classe :)
fonte
Além dos pontos muito bons que outros fizeram, acho que há outro motivo: e se a superclasse não tiver uma superclasse?
Como toda classe se estende naturalmente (pelo menos)
Object
,super.whatever()
sempre se refere a um método na superclasse. Mas e se a sua aula se estender apenasObject
- a que sesuper.super
referiria então? Como esse comportamento deve ser tratado - um erro do compilador, um NullPointer, etc?Eu acho que a principal razão pela qual isso não é permitido é que viola o encapsulamento, mas isso também pode ser uma pequena razão.
fonte
Eu acho que se você sobrescrever um método e quiser toda a versão de
equals
superclasse (como, digamos, por ), então você praticamente sempre chamará a versão direta da superclasse primeiro, que chamará sua versão da superclasse por sua vez, se quiser .Eu acho que raramente faz sentido (se é que não consigo pensar em um caso em que isso ocorre) chamar a versão de um método de alguma superclasse arbitrária. Não sei se isso é possível em Java. Isso pode ser feito em C ++:
fonte
Em suposição, porque não é usado com tanta frequência. A única razão pela qual pude ver usá-lo é se seu pai direto substituiu alguma funcionalidade e você está tentando restaurá-lo de volta ao original.
O que me parece contrário aos princípios da OO, uma vez que os pais diretos da classe devem estar mais intimamente relacionados à sua classe do que o avô.
fonte
Veja este projeto do Github, especialmente a variável objectHandle. Este projeto mostra como realmente e com precisão chamar o método de avô em um neto.
Apenas no caso de o link ser quebrado, aqui está o código:
Feliz codificação !!!!
fonte
Eu colocaria o corpo do método super.super em outro método, se possível
Ou, se você não pode alterar a classe super-super, pode tentar o seguinte:
Nos dois casos, o
resultados para "eu sou super super"
fonte
Parece ser possível obter pelo menos a classe da superclasse da superclasse, embora não necessariamente a instância dela, usando reflexão; se isso for útil, considere o Javadoc em http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Class.html#getSuperclass ()
fonte
execução: UM CONSTRUÇÃO BEM SUCEDIDA (tempo total: 0 segundos)
fonte
A chamada de super.super.method () faz sentido quando você não pode alterar o código da classe base. Isso geralmente acontece quando você está estendendo uma biblioteca existente.
Pergunte a si mesmo primeiro, por que você está estendendo essa aula? Se a resposta for "porque não posso alterá-la", você poderá criar pacote e classe exatos no seu aplicativo e reescrever o método impertinente ou criar delegado:
Por exemplo, você pode criar a classe org.springframework.test.context.junit4.SpringJUnit4ClassRunner em seu aplicativo, para que essa classe seja carregada antes da real do jar. Em seguida, reescreva métodos ou construtores.
Atenção: Este é um hack absoluto, e não é altamente recomendável usar, mas está FUNCIONANDO! O uso dessa abordagem é perigoso devido a possíveis problemas com os carregadores de classes. Além disso, isso pode causar problemas sempre que você atualizar a biblioteca que contém a classe substituída.
fonte
Eu tive situações como estas quando a arquitetura é criar funcionalidades comuns em um CustomBaseClass comum que implementa em nome de várias classes derivadas. No entanto, precisamos contornar a lógica comum para um método específico para uma classe derivada específica. Nesses casos, devemos usar uma implementação super.super.methodX.
Conseguimos isso introduzindo um membro booleano no CustomBaseClass, que pode ser usado para adiar seletivamente a implementação customizada e render a implementação da estrutura padrão, sempre que desejável.
No entanto, com bons princípios de arquitetura seguidos na estrutura e no aplicativo, poderíamos evitar essas situações facilmente, usando a abordagem hasA, em vez da abordagem isA. Mas, a todo momento, não é muito prático esperar uma arquitetura bem projetada e, portanto, a necessidade de se afastar de princípios sólidos de design e introduzir hacks como esse. Apenas meus 2 centavos ...
fonte
@ Jon Skeet Boa explicação. IMO, se alguém quiser chamar o método super.super, deve ignorar o comportamento do pai imediato, mas deseja acessar o comportamento do pai principal. Isso pode ser alcançado através da instância Of. Como código abaixo
Aqui está a classe do driver,
A saída disso será
O comportamento da classe B printClass será ignorado nesse caso. Não tenho certeza sobre isso é uma prática ideal ou boa para obter super.super, mas ainda está funcionando.
fonte
Se você acha que vai precisar da superclasse, pode referenciá-la em uma variável para essa classe. Por exemplo:
Deve imprimir:
fonte
new UltraFoo.getNumber()
não vou compilar, pois você perdeu parênteses lá. No entanto, acabei de remover meu donvote, pois o conceito do seu código está bem claro agora, obrigado!IMO, é uma maneira limpa de obter
super.super.sayYourName()
comportamento em Java.Resultado:
Request to lie: d.sayYourName(true) returns Grandma Fedora
Request not to lie: d.sayYourName(false) returns Little girl Masha
fonte
Eu acho que esse é um problema que quebra o contrato de herança.
Ao estender uma aula, você obedece / concorda com seu comportamento,
enquanto Embora ao ligar
super.super.method()
, deseja quebrar seu próprio acordo de obediência.Você simplesmente não pode escolher a super classe .
No entanto, pode ocorrer situações em que você sinta necessidade de ligar
super.super.method()
- geralmente um sinal de design ruim, no seu código ou no código que você herdou!Se as super e super super classes não puderem ser refatoradas (algum código legado), opte pela composição em vez da herança.
Quebra de encapsulamento é quando você @ Substitui alguns métodos quebrando o código encapsulado. Os métodos projetados para não serem substituídos são marcados como finais .
fonte
Em C #, você pode chamar um método de qualquer ancestral como este:
Você também pode fazer isso no Delphi:
Mas em Java você pode fazer esse foco apenas de alguma forma. Uma maneira possível é:
saída do resultado objC.DoIt ():
fonte
É simplesmente fácil de fazer. Por exemplo:
Subclasse C da subclasse B e B de A. Os três têm o método methodName () por exemplo.
Executar classe C A saída será: Classe A Classe C
Em vez de saída: Classe A Classe B Classe C
fonte
Saída: Impresso no GrandDad
fonte
super.super.method()
código não é válido em Java.A palavra-chave super é apenas uma maneira de chamar o método na superclasse. No tutorial de Java: https://docs.oracle.com/javase/tutorial/java/IandI/super.html
Se o seu método substituir um dos métodos da superclasse, você poderá invocar o método substituído usando a palavra-chave super.
Não acredite que é uma referência do super objeto !!! Não, é apenas uma palavra-chave para invocar métodos na superclasse.
Aqui está um exemplo:
Quando você liga
cat.doSth()
, o métododoSth()
em classeAnimal
é impressothis
e é um gato.fonte