Pergunta

Eu estou praticando para um exame, e encontrou um problema de amostra que me deixa totalmente perdido. Para o seguinte código, encontrar o que a saída é:

class Moe {
    public void print(Moe p) {
        System.out.println("Moe 1\n");
    }
}
class Larry extends Moe {
    public void print(Moe p) {
        System.out.println("Larry 1\n");
    }
    public void print(Larry l) {
        System.out.println("Larry 2\n");
    }
}
class Curly extends Larry {
    public void print(Moe p) {
        System.out.println("Curly 1\n");
    }
    public void print(Larry l) {
        System.out.println("Curly 2\n");
    }
    public void print(Curly b) {
        System.out.println("Curly 3\n");
    }
}
public class Overloading_Final_Exam {
    public static void main (String [] args) {
        Larry stooge1 = new Curly();
        Moe stooge2 = new Larry();
        Moe stooge3 = new Curly();
        Curly stooge4 = new Curly();
        Larry stooge5 = new Larry();
        stooge1.print(new Moe()); 
        ((Curly)stooge1).print(new Larry()); 
        ((Larry)stooge2).print(new Moe()); 
        stooge2.print(new Curly()); 
        stooge3.print(new Curly()); 
        stooge3.print(new Moe()); 
        stooge3.print(new Larry()); 
        ((Curly)stooge3).print(new Larry()); 
        ((Curly)stooge3).print(new Curly()); 
        stooge4.print(new Curly()); 
        stooge4.print(new Moe()); 
        stooge4.print(new Larry()); 
        stooge5.print(new Curly()); 
        stooge5.print(new Larry()); 
        stooge5.print(new Moe()); 
    }
}

Eu tive as minhas ideias em mente, mas, em seguida, quando eu corria o java, eu tenho algo totalmente diferente:

Curly 1
Curly 2
Larry 1
Larry 1
Curly 1
Curly 1
Curly 1
Curly 2
Curly 3
Curly 3
Curly 1
Curly 2
Larry 2
Larry 2
Larry 1

As primeiras queridos estão OK, mas então eu realmente não entendo. Alguém tem uma boa explicação para este problema?

Graças

Foi útil?

Solução

Gostaria de começar por fazer um desenho ...

Moe - print(Moe)
 |
Larry - print(Moe), print(Larry)
 |
Curly - print(Moe), print(Larry), print(Curly)

Então gostaria de manter o controle das variáveis:

  • Larry - stooge1 -> Curly
  • Moe - stooge2 -> Larry
  • Moe - stooge3 -> Curly
  • Curly - stooge4 -> Curly
  • Larry - stooge5 -> Larry

  • stooge1.print(new Moe())

    • stooge1 -> Curly por isso chama Curly.print (Moe)
  • ((Curly)stooge1).print(new Larry());

    • stooge1 -> Curly por isso chama Curly.print (nova Larry ())
  • ((Larry)stooge2).print(new Moe());

    • stooge2 -> Larry assim chama Larry.print (novo Moe ());
  • stooge2.print(new Curly());
    Ok, isso é onde fica um pouco mais complicado (desculpe eu parei um antes aqui)

    • stooge2 é declarado para ser um Moe. Então, quando o compilador está olhando para o que chamar ele vai chamar o método de impressão (Moe). Em seguida, em tempo de execução ele sabe que stooge2 é um Larry para que ele chama o método Larry.print (Moe).

etc ...

Deixe-me saber se segue que todo o caminho não funciona para você.

(atualizado para esclarecer o próximo)

Portanto, a regra geral é:

  • os olhares do compilador no tipo de variável para decidir o método a chamada.
  • a aparência de tempo de execução na classe real que a variável é ponto em que decidir onde obter o método de.

Então, quando você tem:

Moe stooge2 = new Larry();
stooge2.print(new Moe());

o compilador diz:

  • pode Larry ser atribuído a stooge2? (Sim como Larry é uma subclasse de Moe)
  • não Moe tem um método print (Moe)? (Sim)

o tempo de execução diz:

  • eu deveria chamar o método print (Moe) neste objecto aqui ... stooge2
  • stooge2 é ponto de cada Larry.
  • Eu vou chamar o método print (Moe) na classe Larry.

Depois de ter trabalhado tudo o que fora tentar se livrar de alguns dos métodos e ver como isso muda as coisas.

Outras dicas

Na verdade, este problema não é tão simples como parece, já que Java é tanto estática e ligada dinamicamente. Você tem que entender onde cada um é aplicado antes de você vai entender todos os resultados que estão recebendo a partir deste exercício.

A regra geral mencionado por TofuBeer só é correta no caso de ligação dinâmica. Na ligação estática, as decisões são feitas apenas em tempo de compilação.

Seus exemplo misturas a ligação dinâmica (quando os métodos são substituídas) e estáticas de ligação (quando os métodos são sobrecarregados).

neste questão para mais detalhes .

Uma dica é desconsiderar o valor do lado esquerdo quando se olha para objetos. Em vez disso, olhar para o valor do direito durante a declaração, este é o valor real do objeto.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top