Warum ist diese Java -Methode polymorphing nach deklarierter Typ und nicht nach Laufzeittyp?

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

  •  26-10-2019
  •  | 
  •  

Frage

Dieser 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();
        }
    }
}

erzeugt diese Ausgabe:

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

Ich kann sehr deutlich erkennen, dass die Methode der Aufgaben über die Methode der Aktion ausgewählt wird. Ich verstehe jedoch nicht, warum, da die Objekte immer wissen, was sie sind, und ich dachte, Javas Auswahl für spätbindende Methoden würde den Unterschied in den Methodensignaturen unterscheiden. Der Anruf an bar() ist besonders verwirrend wie task wird als ein deklariert Action an diesem Punkt.

Wenn es einen Unterschied macht, ist dies 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)

Ich kann meinen Code ändern, damit er funktioniert, aber ich würde gerne verstehen, warum er nicht funktioniert. Danke für die Hilfe!

War es hilfreich?

Lösung

So funktioniert der Versand in Java.

Der Versand basiert zunächst auf statischen Parametertypen, und sobald eine statische Signatur ausgewählt wurde, wird der Laufzeittyp des Objekts, das die Methode enthält, herausgefunden, welche Überschreibung verwendet wird.

Zum Beispiel in

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).

Andere Tipps

Die Auswahl zwischen überlasteten Methoden wird immer zur Kompilierungszeit getroffen, niemals zur Laufzeit. Die Laufzeitpolymorphismus beinhaltet die Auswahl zwischen Methoden, die andere Methoden überschreiben - dh Methoden mit identischen Signaturen.

Denn sobald du vorbeikommst Server hinein foo oder bar, im Rahmen dieses Anrufs ist es nicht ein Server sondern eher a Runner.

Deshalb, wenn Sie rennen delegate Es wird gemäß der Signatur der Methode an die am besten geeignete Übereinstimmung gebunden. delegate(Runner) erfordert nicht die gefährliche Niederlage des Scoped -Parameters in a Server.

Beachten Sie, dass dieser Scoping nicht zur Laufzeit durchgeführt wird, sondern auch der statischen Analyse des Quellcodes entspricht. Es ist nur so, dass Sie sich erinnern, dass Server ein war Server Das verwirrt dich. Wenn Sie den Code ohne dieses zusätzliche Wissen außerhalb des Skops analysieren, sehen Sie das delegate(Runner) Wirklich sind Sie nur eine gültige Wahl.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top