it-swarm.com.de

Java - warum keine rückgabetypbasierte Methodenüberladung?

Ich weiß, dass dies nicht möglich ist, aber kann jemand eine Theorie liefern, warum Java dies nicht unterstützt? Ich frage, weil ich gerade in eine Situation geraten bin, in der ich denke es schön wäre, sie zu haben.

42
llm

Da Sie den Rückgabewert einer Methode in Java nicht erfassen müssen, kann der Compiler nicht entscheiden, welche Überladung verwendet werden soll. Z.B.

boolean doSomething() { ... }

int doSomething() { ... }

doSomething(); // which one to call???
75
Péter Török

Ein interessanter Aspekt dieser Frage ist die Tatsache, dass die Java-Sprache das Überladen von Methoden nur durch den Rückgabetyp verbietet. Aber nicht die JVM:

Beachten Sie, dass es in einer Klasse mehrere Übereinstimmende Methoden geben kann, da , Während die Java-Sprache einer Klasse verbietet, mehrere Methoden mit Der gleichen Signatur zu deklarieren Unterschiedliche Rückgabetypen, die Java Virtual Machine nicht. Diese erhöhte Flexibilität In der virtuellen Maschine kann verwendet werden, um Verschiedene Sprachmerkmale zu implementieren. Zum Beispiel können kovariante Rückgaben Mit Brückenmethoden implementiert werden. Die Brückenmethode und die Methode, die überschrieben wird, hätte dieselbe Signatur , jedoch unterschiedliche Rückgabetypen.

Von: Class.getMethod (String, Class ...)

31
Lukas Eder

Ich habe mich gefragt, warum sie das auch nicht unterstützen. Sicher, wenn Sie den Rückgabewert ignorieren, kann der Compiler nicht wissen, was Sie wollten. Das ist jedoch die gleiche Mehrdeutigkeit, die sich mit dem Übergeben von Nullen ergibt. Mögen:

String doSomething(String s) { ... }
String doSomething(Integer s) { ... }
...
String out=doSomething(null);

In diesem Fall beschwert sich der Compiler nur, dass der Aufruf mehrdeutig ist, und Sie müssen ihn auflösen, indem Sie die NULL umwandeln, z.

String out=doSomething((String)null);

Sie können dasselbe mit Überladen durch Rückgabetyp machen:

String getSomething() { ... }
Integer getSomething() { ... }
...
Integer n=getSomething();

würde vermutlich die zweite Funktion aufrufen.

getSomething();

wäre mehrdeutig (und in diesem Beispiel wahrscheinlich nutzlos, es sei denn, es hatte Nebenwirkungen, aber das ist eine andere Geschichte), so müssten Sie sagen:

(String) getSomething();

Realistischer vielleicht:

if ((String) getSomething()==null) ...

Aber das ist der einfache Fall. Ich kann einen Compiler-Writer sehen, der das nicht unterstützen will, weil es sehr kompliziert werden könnte, etwas anderes als eine einfache Aufgabe herauszufinden. Betrachten Sie zum Beispiel:

String getSomething() { ... };
Integer getSomething() { ... };
String getOtherthing() { ... };
...
if (getSomething().equals(getOtherthing())) ...

Der Compiler müsste herausfinden, dass sowohl String als auch Integer Gleichheitsfunktionen haben, daher ist eine der beiden zu diesem Zeitpunkt gültig. Dann müsste man feststellen, dass getOtherthing ein String ist und Integer.equals (String) unwahrscheinlich ist. Wahrscheinlich wollte der Writer String.equals (String). Machbar, aber zu diesem Zeitpunkt beginne ich zu sehen, dass dies im allgemeinen Fall eine Bestie sein könnte.

Und dann nehmen wir an, wir fügen hinzu:

Integer getOtherthing() { ... };

Was macht nun der Compiler mit dieser IF-Anweisung? Es können die String-Versionen beider Funktionen oder die Ganzzahl verwendet werden, nicht jedoch die Zeichenfolge der einen und die Ganzzahl der anderen. An diesem Punkt müsste es auf einem Cast bestehen, um ihm zu sagen, was ich vermute. Aber die Komplexität gerät wirklich außer Kontrolle.

Und wenn es für den Compiler schwierig ist, herauszufinden, was Sie wirklich meinen, dann stellen Sie sich vor, wie es für einen anderen Programmierer wäre, der nicht alle Funktionssignaturen so schnell wie der Compiler nachschlagen kann.

13
Jay

Sie können den Rückgabewert ignorieren.

3
Tadeusz Kopec

Obwohl dies theoretisch möglich ist, wurde es in Java nicht aus dem gleichen Grund verwendet wie in C++. Es hat sich nämlich herausgestellt, dass Überladungen auf der Grundlage von Rückgabetypen für Entwickler in der Regel verwirrender sind. Der Nutzen ist im Vergleich zu den Kosten für die Implementierung gering, und es wäre mehrdeutig, wenn der Rückgabetyp keinem Server zugewiesen wird Wert. Aus diesen Gründen wird eine Überladung auf Grundlage des Rückgabetyps nicht unterstützt.

Ich denke, einer der Gründe ist, dass Sie den Rückgabetyp einer Funktion in den meisten Fällen erst nach der Ausführung der Funktion statt vor diesem Prozess bestimmen können. Daher kann es nicht helfen, zu entscheiden, welche überladene Funktion nur auf der Grundlage verschiedener Rückgabetypen von Funktionen aufgerufen wird.

Die Methodenüberladung verwendet die Kompilierzeit-Polymorphismus-Technik. Beim Überschreiben von Methoden wird die Laufzeit-Polymorphismus-Technik verwendet.

Überladung der Methode:

Wie in den vorherigen Antworten bereits erwähnt, unterstützt Java keine Methodenüberladung mit einem anderen Rückgabetyp und denselben Argumenten. Dies liegt daran, dass festgelegt werden muss, welche Methode zur Kompilierzeit selbst verwendet wird. Um die Mehrdeutigkeit zu beseitigen, entwickelten sie die Methode zum Überladen von Methoden wie folgt.

Wenn Methoden wirklich mit verschiedenen Typen und gleichen Argumenten überladen werden müssen, ist es möglich, dass mehtod überschreibt.

Überschreiben der Methode:

Das Überschreiben von Methoden verwendet eine Laufzeit-Polymorphismus-Technik. Welche Methode ausgeführt wird, wird daher nicht zur Kompilierzeit festgelegt und zur Laufzeit von der JVM festgelegt.

Bei co-varianten Rückgabetypen können wir in der Methode der Unterklasse einen anderen Rückgabetyp mit denselben Argumenten wie die Basisklasse verwenden.

Beispiel für eine Variante mit co-variierter Rückgabe:

            class BaseClass {
                BaseClass dosomething(){
                    System.out.println("Print BaseClass");
                    return this;
                }

            }

            class AnotherBaseClass extends BaseClass {
                @Override
                BaseClass dosomething(){
                    System.out.println("Print AnotherBaseClass");
                    return this;
                }
            }



            class SubClass extends AnotherBaseClass {
                @Override
                SubClass dosomething(){ /*Here SubClass is co-vairantreturn type*/ 
                    System.out.println("Print SubClass");
                    return this;
                }
                public static void main(String args[]){
                  SubClass s1 = new SubClass();
                  s1.dosomething();
                }
            }

Ausgabe: 

Unterklasse drucken

0
SARIKA

Überladen-Funktion nur auf der Grundlage des Rückgabetyps ist für den Compiler verwirrend, um zwischen den Aufrufen zu unterscheiden, da Sie zum Zeitpunkt des Aufrufs nicht den Rückgabetyp wie in den Parametern angeben, so dass Sie nur die Parameterliste und angeben Diese Parameterliste ist die einzige Möglichkeit für den Compiler, zwischen den Funktionsaufrufen zu unterscheiden, und der Rückgabewert wird bei Abschluss der Funktion empfangen. Aus diesem Grund trägt der Rückgabetyp nicht zur Signatur der Funktion bei

0
Saifullah Memon