# Methoden überlagern



## famco (10. Apr 2011)

Hallo,
ich habe mir eine kleine Klasse geschrieben, mit der ich etwas komfortabler mit Kommandozeilenargumenten umgehen kann. Bisher konnte sie nur Stringparameter zurückgeben. Jetzt habe ich mir überlegt, dass ich die Methode überlagere und somit auch die Übergabe von int-Parametern ermögliche:

```
:
    public String Argument(String selektor) {   // Selektor suchen
        int p = this.argumente.indexOf(selektor.trim());
        if (p < 0) { // nicht gefunden
            return "";
        }
        return this.argumente.substring(p + selektor.length(), this.argumente.indexOf(' ', p)).trim();
    }

    public int Argument(String selektor) {
        int p = this.argumente.indexOf(selektor.trim());
        if (p < 0) { // nicht gefunden
            return 0;
        }
        return Integer.parseInt(this.argumente.substring(p + selektor.length(), this.argumente.indexOf(' ', p)).trim());
    }
:
```
Obwohl die beiden Methodenheader gleich sind, weist der Compiler die Klasse ab.
Was mache ich falsch ?
Danke


----------



## XHelp (10. Apr 2011)

ne, überladen ist was anderes:

```
int someMethod(String parameter) {...}
int someMethod(int parameter) {...}
int someMethod(double parameter1, Object parameter2) {...}
```
usw.
Wie soll denn sonst deiner Meinung nach entschieden werden welche Methode aufgerufen werden sollte?


----------



## awda23ws23 (10. Apr 2011)

Im Gegsatz zu anderen Sprachen betrachtet Java nur die Parameter und nicht die Rückgabewerte als Methodensignatur


----------



## kirax (10. Apr 2011)

awda23ws23 hat gesagt.:


> Im Gegsatz zu anderen Sprachen betrachtet Java nur die Parameter und nicht die Rückgabewerte als Methodensignatur



Und das aus gutem Grund


----------



## Firephoenix (10. Apr 2011)

Hi,
Wäre es nicht einfach immer den String einzulesen und als Ersatz im eigentlichen Programm eine Funktion zu schreiben, die versucht den String in einen Int zu parsen, schlägt das fehl wird der User wieder nach einem Int gefragt, solange bis er einen gültigen eingibt.
Gruß


----------



## Landei (11. Apr 2011)

awda23ws23 hat gesagt.:


> Im Gegsatz zu anderen Sprachen betrachtet Java nur die Parameter und nicht die Rückgabewerte als Methodensignatur



Das stimmt nicht ganz. Die JVM kann Methoden sehr wohl nach dem Rückgabewert unterscheiden, und Java nutzt das an einer Stelle: Bei "synthetisch" generierten (oder "Brücken-") Methoden, die der Compiler einfügt, um Generics zum Laufen zu bekommen (ich kann auf Wunsch die gruseligen Details nachschlagen). Nur uns Normalsterblichen bleibt dieser Luxus verwehrt - Quod licet Iovi, non licet bovi...


----------



## kirax (11. Apr 2011)

Ok die gruseligen Details interessieren mich dann schon... interessant


----------



## famco (11. Apr 2011)

Klar kann ich beim Aufrufer das Ergebnis wandeln, aber dass muss ich dann an vielen Stellen machen.
Schade, dass der Rückgabewert nicht zur Signatur der Methode zählt. Wäre irgendwie eleganter. So könnte je nach Methodenaufruf ein passender Typ zurückgegeben werden.
Danke


----------



## Firephoenix (11. Apr 2011)

Hi,
wenn du das an vielen Stellen machen musst, warum schreibst du dir dann nicht eine Methode, die die andere Kapselt?
Ob du dann deine normale einlesen verwendest oder die Methode die erst einlesen aufruft und das Ergebnis in einen int konvertiert gibt sich doch nichts?
Gruß


----------



## famco (11. Apr 2011)

ja schon klar, wäre nur irgendwie elaganter gewesen .... 
Danke


----------



## Landei (11. Apr 2011)

Man *kann* mit Generics einen flexiblen Rückgabewert "simulieren" - aber wegen Type Erasure nur, wenn man den korrekten Typ irgendwie aus den Argumenten ermitteln kann (notfalls durch Übergabe eines [c]java.lang.Class[/c]-Objekts). Beispiel:


```
public class ReturnValue {
 
    public static <T> T argument(String selector) {
        if (selector.equals("integer")) return (T) Integer.valueOf(42);
        if (selector.equals("string")) return (T) "answer";
        return null;
    }
    
    public static void main(String[] args) {
        String s = argument("string");
        int i = argument("integer");
        System.out.println(s + " " + i);
    }
}
```

Falls es sich dabei nicht um externe Daten (wie z.B. ein geparstes File) handelt, deutet die Notwendigkeit für solche Hacks allerdings auf ein Designproblem hin.


----------



## famco (11. Apr 2011)

ja, das ist auch eine gute Idee. Danke.


----------



## kirax (11. Apr 2011)

@Landei
Aber das ist schon sehr eklig 
Ähnliches ließe sich ja auch mit Object machen, falls man auf Java < 5 zurückgreifen muss


----------



## Landei (11. Apr 2011)

Hier die versprochenen Details zu Brückenmethoden. Es gibt welche für covariante Rückgabetypen:



> Zusätzlich zur covarianten überschriebenen Methode fügt der Compiler in die Subklasse jede der überschriebenen Methoden mit dem Return-Type der Supertypen hinzu. Diese rufen dann in der return-Anweisung die contravarianten Methoden mit den aktuellen Argumenten auf


(Java 5 im Einsatz, Friedrich Esser, Galileo Computing, S. 78)

Hat man also sowas:

```
interface Foo {
    Number get();
}

class FooImpl implements Foo {
   Integer get() { return 42; }
}
```

... dann findet man in der decompilierten Klasse von FooImpl eine zweite get-Methode [c]Number get(){ return get(); }[/c], wobei das darin aufgerufene get die covariante Methode (mit dem Rückgabetyp Integer) ist. Wie gesagt kann die JVM beide Versionen unterscheiden.

Dann gibt es Bridge-Methoden bei generischen Hierarchien:



> Der Compiler fügt für alle Methoden der Supertypen eines Subtyps D Bridge-Methoden in D ein, wenn
> - D die Methoden dieser Supertypen direkt mit einem anderen Raw-Type überschreibt.
> - in D die Methoden dieser Supertypen zwar nicht direkt überschrieben werden, aber mit einem anderen Raw-Type aufgerufen werden kann (d.h. diese Methode nicht abstract ist)
> 
> Der Type einer Bridge-Methode ist der des Raw-Types der Superklasse, die die überschriebene Methode als letzte implementiert oder deklariert hat. In der Methode werden evt. vorhandene generische Argumente zum Raw-Type des Subtypen gecastet und - sofern vorhanden -  die Subtyp-Methode aufgerufen oder ansonsten die Supertyp-Methode


(ebd., S. 79)

Ich will eigentlich nicht genauer über diese Sätze nachdenken. Fakt ist, es gibt Brücken-Methoden, und da diese direkt vom Compiler eingefügt werden, unterliegen diese nicht den Beschränkungen, dass eine Methoden-Auflösung den Rückgabewert nicht berücksichtigen darf, sondern nutzen dieses Feature aus. Das erklärt auch, warum man Name-Clashes mit Methoden bekommen kann, die man gar nicht in der Klasse definiert hat - man ist auf eine Brücken-Methode gestoßen.


----------



## Landei (12. Apr 2011)

Ach ja, hier werden Brückenmethoden recht gut erklärt: Generics in Java 1.5


----------

