public class SuperClass
{
public void method1()
{
System.out.println("superclass method1");
this.method2();
}
public void method2()
{
System.out.println("superclass method2");
}
}
public class SubClass extends SuperClass
{
@Override
public void method1()
{
System.out.println("subclass method1");
super.method1();
}
@Override
public void method2()
{
System.out.println("subclass method2");
}
}
public class Demo
{
public static void main(String[] args)
{
SubClass mSubClass = new SubClass();
mSubClass.method1();
}
}
minha saída esperada:
subclasse método1
superclasse método1
superclasse método2
saída real:
subclasse método1
superclasse método1
subclasse método2
Sei que tecnicamente substituí um método público, mas percebi que, como estava chamando o super, todas as chamadas dentro do super permaneceriam no super, isso não está acontecendo. Alguma ideia de como posso fazer isso acontecer?
java
inheritance
overriding
super
jsonfry
fonte
fonte
Respostas:
A palavra-chave
super
não "gruda". Cada chamada de método é tratada individualmente, portanto, mesmo que você tenha feito issoSuperClass.method1()
chamandosuper
, isso não influencia nenhuma outra chamada de método que possa ser feita no futuro.Isso significa que não há nenhuma maneira direta para chamar
SuperClass.method2()
deSuperClass.method1()
sem ir emboraSubClass.method2()
, a menos que você está trabalhando com uma instância real deSuperClass
.Você nem consegue obter o efeito desejado usando o Reflection (consulte a documentação de
java.lang.reflect.Method.invoke(Object, Object...)
).[EDIT] Ainda parece haver alguma confusão. Deixe-me tentar uma explicação diferente.
Quando você invoca
foo()
, você realmente invocathis.foo()
. Java simplesmente permite que você omita othis
. No exemplo da pergunta, o tipo dethis
éSubClass
.Então, quando Java executa o código
SuperClass.method1()
, ele finalmente chega emthis.method2();
Usar
super
não altera a instância apontada porthis
. Portanto, a chamada vai para,SubClass.method2()
poisthis
é do tipoSubClass
.Talvez seja mais fácil entender quando você imagina que Java passa
this
como um primeiro parâmetro oculto:Se você seguir a pilha de chamadas, verá que
this
nunca muda, é sempre a instância criada emmain()
.fonte
super
. Cada vez que ele chama um método, ele examina o tipo de instância e começa a pesquisar o método com este tipo, não importa quantas vezes você o chamesuper
. Portanto, quando você chamamethod2
uma instância deSubClass
, ela sempre verá aSubClass
primeira.super
não altera a instância. Ele não define algum campo oculto "de agora em diante, todas as chamadas de método devem começar a usarSuperClass
". Ou, dito de outra forma: o valor dethis
não muda.Você só pode acessar métodos substituídos nos métodos de substituição (ou em outros métodos da classe de substituição).
Portanto: não substitua
method2()
ou chamesuper.method2()
dentro da versão substituída.fonte
Você está usando a
this
palavra - chave que na verdade se refere à "instância atualmente em execução do objeto que você está usando", ou seja, você está invocandothis.method2();
em sua superclasse, ou seja, ele chamará o método2 () no objeto que você ' está usando, que é a SubClass.fonte
this
também não ajudará. Uma invocação não qualificada usa implicitamentethis
method2()
o compilador veráthis.method2()
. Portanto, mesmo que você remova o,this
ele não funcionará. O que @Sean Patrick Floyd está dizendo está corretothis
this
se refere à "classe de instância de execução concreta" (conhecida em tempo de execução) e não (como o autor da postagem parece acreditar) à "classe de unidade de compilação atual" (onde a palavra-chave é usada, conhecida em tempo de compilação). Mas também pode ser enganoso (como Shervin aponta):this
também é referenciado implicitamente com a chamada de método simples;method2();
é o mesmo quethis.method2();
Eu penso assim
Deixe-me mover essa subclasse um pouco para a esquerda para revelar o que está por baixo ... (Cara, eu adoro gráficos ASCII)
Em outras palavras, citando a Especificação da linguagem Java :
Em termos leigos,
this
é basicamente um objeto (* o ** objeto; o mesmo objeto que você pode mover em variáveis), a instância da classe instanciada, uma variável simples no domínio de dados;super
é como um ponteiro para um bloco de código emprestado que você deseja que seja executado, mais como uma mera chamada de função e é relativo à classe onde é chamado.Portanto, se você usar
super
da superclasse, você obterá o código da classe superduper [o avô] executado), enquanto se você usarthis
(ou se for usado implicitamente) de uma superclasse, ele continuará apontando para a subclasse (porque ninguém a alterou - e ninguém poderia).fonte
Se você não quiser que superClass.method1 chame subClass.method2, torne o método2 privado para que ele não possa ser substituído.
Aqui está uma sugestão:
Se não funcionasse assim, o polimorfismo seria impossível (ou pelo menos nem metade da utilidade).
fonte
Visto que a única maneira de evitar que um método seja sobrescrito é usar a palavra - chave super , pensei em mover o método2 () de SuperClass para outra nova classe Base e, em seguida, chamá-lo de SuperClass :
Resultado:
fonte
this
sempre se refere ao objeto atualmente em execução.Para ilustrar melhor o ponto aqui está um esboço simples:
Se você tem uma instância da caixa externa, um
Subclass
objeto, onde quer que você se aventure dentro da caixa, mesmo naSuperclass
"área", ainda é a instância da caixa externa.Além do mais, neste programa há apenas um objeto que é criado a partir das três classes, portanto,
this
só pode se referir a uma coisa e é:conforme mostrado no 'Heap Walker' do Netbeans .
fonte
chamando
saídas
fonte
Não acredito que você possa fazer isso diretamente. Uma solução alternativa seria ter uma implementação interna privada do método2 na superclasse e chamá-la. Por exemplo:
fonte
"this" palavra-chave refere-se à referência de classe atual. Isso significa que, quando usada dentro do método, a classe 'atual' ainda é SubClasse e, portanto, a resposta é explicada.
fonte
Para resumir, isso aponta para o objeto atual e a invocação do método em java é polimórfica por natureza. Portanto, a seleção do método para execução depende totalmente do objeto apontado por este. Portanto, invocar o método method2 () da classe pai invoca o método2 () da classe filha, pois this aponta para o objeto da classe filha. A definição disso não muda, independentemente da classe usada.
PS. ao contrário dos métodos, as variáveis de membro da classe não são polimórficas.
fonte
Durante minha pesquisa para um caso semelhante, acabei verificando o rastreamento da pilha no método da subclasse para descobrir de onde vem a chamada. Provavelmente existem maneiras mais inteligentes de fazer isso, mas funciona para mim e é uma abordagem dinâmica.
Acho razoável a questão de ter uma solução para o caso. É claro que existem maneiras de resolver o problema com nomes de métodos diferentes ou até mesmo tipos de parâmetros diferentes, como já mencionado no segmento, mas no meu caso não gosto de confundir com nomes de métodos diferentes.
fonte
Mais estendida a saída da questão levantada, isso dará mais informações sobre o especificador de acesso e o comportamento de substituição.
fonte