Pourquoi cette méthode Java polymorphing par type déclaré et non le type d'exécution?

StackOverflow https://stackoverflow.com/questions/5331620

  •  26-10-2019
  •  | 
  •  

Question

Ce code:

public class PMTest
{

    private static class Runner { }
    private static class Server extends Runner { }

    private static class Task
    {
        public void delegate(Runner runner)
        {
            System.out.println("Task: " + runner.getClass().getName() +
                               " / " + this.getClass().getName());
        }
    }

    private static class Action extends Task
    {
        public void delegate(Server server)
        {
            System.out.println("Action: " + server.getClass().getName() +
                               " / " + this.getClass().getName());
        }
    }


    private static void foo(Task task, Runner runner)
    {
            task.delegate(runner);
    }

    private static void bar(Action task, Runner runner)
    {
            task.delegate(runner);
    }

    private static void baz(Action task, Server runner)
    {
            task.delegate(runner);
    }


    public static void main (String[] args)
    {
        try {
            Server server = new Server();
            Action action = new Action();

            action.delegate(server);
            foo(action, server);
            bar(action, server);
            baz(action, server);

        }
        catch (Throwable t) {
            t.printStackTrace();
        }
    }
}

produit cette sortie:

$ java PMTest
Action: PMTest$Server / PMTest$Action
Task: PMTest$Server / PMTest$Action
Task: PMTest$Server / PMTest$Action
Action: PMTest$Server / PMTest$Action

Je vois très clairement que la méthode de travail est choisi sur la méthode d'action. Je ne comprends pas pourquoi, bien que, puisque les objets savent toujours ce qu'ils sont et je pensais que la sélection de la méthode de liaison tardive de Java serait en mesure de distinguer la différence dans les signatures de méthode. L'appel à bar() est particulièrement déroutant, comme task est déclarée comme Action à ce moment-là.

Si cela fait une différence, c'est Java 6:

$ java -version
java version "1.6.0_14"
Java(TM) SE Runtime Environment (build 1.6.0_14-b08)
BEA JRockit(R) (build R27.6.5-32_o-121899-1.6.0_14-20091001-2113-linux-ia32, compiled mode)

Je peux changer mon code pour le faire fonctionner, mais je voudrais comprendre pourquoi il ne fonctionne pas. Merci pour l'aide!

Était-ce utile?

La solution

C'est comment fonctionne l'expédition en java.

expédition est basée d'abord sur les types de paramètres statiques, et une fois une signature statique a été choisi, le type d'exécution de l'objet contenant la méthode est utilisée pour déterminer quels remplaçant est utilisé.

Par exemple, dans

void foo(Object o) {
  if (o instanceof Number) { foo((Number) o); }
  else if (o instanceof String) { foo((String) o); }
}

void foo(String s) { ... }

void foo(Number n) { ... }

{ foo((Object) "foo"); }  // Calls foo(Object) which calls foo(String).
{ foo("foo"); }  // Calls foo(String) without first calling foo(Object).

Autres conseils

Le choix entre les méthodes surchargées est toujours faite au moment de la compilation, jamais lors de l'exécution. Durée polymorphisme consiste à choisir entre les méthodes qui remplacent d'autres méthodes. - à savoir, des méthodes avec des signatures identiques

Parce qu'une fois que vous passez Server dans foo ou bar, dans le cadre de cet appel, il est pas un Server mais plutôt un Runner.

Par conséquent, lorsque vous exécutez delegate, il se lie au match le plus approprié, en fonction de la signature de la méthode. delegate(Runner) ne nécessite pas baissés dangereux du paramètre scope dans une Server.

Notez que cette portée ne se fait pas à l'exécution, il organisera à l'analyse statique du code source aussi. Il est juste que vous vous souvenez serveur était un Server qui te confondant. Si vous analysez le code sans que la connaissance supplémentaire hors-champ, alors vous verrez que vous delegate(Runner) est vraiment le seul choix valable.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top