2009-05-28 12 views
4

Grundsätzlich was ich will, istwo public Methoden mit etwas anderen Rückgabewerten, um die gleiche Methode aufzurufen, um die erforderliche Arbeit auszuführen. Sie geben beide den Rückgabewert der privaten Methode zurück, aber die private Methode weiß, wie sie den richtigen Wert in Abhängigkeit von der öffentlichen Methode zurückgibt, die sie aufgerufen hat.Ändern eines Rückgabetyps in Abhängigkeit von der aufrufenden Methode

Beispiel Methoden:

public Map<Type1, Type3> doSomething1(); 
public Map<Type2, Type3> doSomething2(); 

private Map<Type1/Type2, Type3> doSomething(); 

im obigen Beispiel also, doSomething() gibt entweder Typ1 oder Typ2 als Key-Typ der Karte, auf der öffentliche Methode sie aufgerufen abhängig. Es wäre in der Lage, eine einfache Überprüfung durchzuführen und die Karte mit Objekten des richtigen Typs zu füllen.

Vielleicht kann dies durch eine clevere Java-Reflektion geschehen? Ich bin mir nicht sicher. Es scheint alles ziemlich doof zu sein, also wenn es einen viel besseren Weg gibt, bin ich ganz Ohr.

Antwort

8

Ich schlage vor, dass Reflexion-mojo hier vermieden werden sollte. Eine Funktion muss eine Eigenschaft erfüllen und darf nicht davon abhängen, wer sie aufruft.

Eine bessere Möglichkeit, dasselbe zu tun, wäre, doSomething() in kleinere Funktionen umzuwandeln, zwei neue Funktionen namens doSomethingFor1() und doSomethingFor2() zu erstellen. Beide Funktionen können die refaktorierten Teile der alten doSomething() wiederverwenden.

Jetzt doSomething1() aufrufen und doSomethingFor1() verwenden.

Ebenso sollte doSomething2() doSomethingFor2() verwenden.

Prost,

jrh.

+0

Ja, das ist es auch, was ich mir ausgedacht habe. Ich stimme zu, dass eine Methode keine Abhängigkeit von ihrem Anrufer haben sollte. Aber was, wenn doSomethingFor1() und doSomethingFor2() den exakt gleichen Code teilen, die einzige Sache, die sie unterscheidet, welches Objekt sie als der Schlüssel zur Karte hinzufügen? Wäre das nicht eine große Duplizierung von Code? –

+2

muss der Duplizierung entgegengewirkt werden, indem die Funktionen ordnungsgemäß umgestaltet und doppelter Code in allgemeine Funktionen/Methoden eingefügt wird. – jrharshath

+0

@Dissonant: Verwenden Sie einen Parameter, um anzugeben, welcher Schlüssel hinzugefügt werden soll.Schliesse nicht darauf, wer dich angerufen hat. –

1

Wenn alles andere fehlschlägt, lassen Sie die private Methode Object zurück und verwenden Sie Umwandlungen in den öffentlichen Methoden.

0

Sie können dies auf jeden Fall tun, indem Sie den Stapel mit Reflexion analysieren. Aber ich würde versuchen, es zu vermeiden, und:

  • Rückkehr Basistyp (oder Objekt) und es richtig in den Anrufern werfen, die Sie tun müssen sowieso
  • einen Parameter auf die private Methode übergibt angibt, irgendwie was zu tun und zurück
1

Die erste Frage ist, warum Sie diese genaue Struktur benötigen.

Aber der sichere Weg ist, um es

public Map<Object, Type3> doSomething(); 

zurückkehren zu machen, wenn es keine gemeinsame geordneter Typ für Typ 1 und Typ 2 ist. Wenn Sie einen gemeinsamen Super-Typ haben, könnten Sie diesen anstelle von Objekt verwenden.

Es wäre am besten, den Code umzuformen, der nicht benötigt wird.

+0

Ich frage mich, wie doSomething() wissen, welche Unterklasse von Object (dh Type1 oder Type2) als Map-Schlüssel hinzufügen? Es muss in der Lage sein, eine Überprüfung durchzuführen. –

1

Ich brauche ein wenig Information, die in Ihrer Frage fehlt, wie zum Beispiel, wie Typ1 und Typ 2 instanziiert werden, da Sie nicht direkt von beliebigen Typparametern instanziieren können. Nun nehmen wir an, dass einige allgemeine Daten verwendet werden, um sowohl Typ 1 als auch Typ 2 zu instanziieren. Ansonsten gibt es keinen guten Grund, eine Methode für beide zu verwenden. Im letzteren Fall würde dies bedeuten, dass eine Funktion zwei verschiedene Dinge basierend auf dem Typ ausführt, was eine schlechte Programmierung ist.Wenn Sie eine Logik haben wollen, die direkt auf der aufrufenden Methode basiert, haben Sie einfach zwei private Methoden und refaktorieren Sie die üblichen Dinge.

Wenn Sie nur die Instantiierung anders machen, basierend auf einige Daten, der einfachste Weg, dies zu tun wäre eine private innere Schnittstelle zu erklären sein:

private interface Instantiator<T> { 

    T getNew(Data data);   

} 

Nimmt man nun an, dass Sie Ihre Typen instanziiert können Sie kann dies tatsächlich verwenden:

als eine Methodensignatur, und die öffentlichen Methoden rufen Sie es mit der entsprechenden Instantiator-Implementierung.

3

Bitte beachten Sie:Ich habe die Frage missverstanden, so dass diese Antwort ist das Gegenteil von dem, was die Frage ist wie gefragt. Ich werde das als Community-Wiki als Referenz hinterlassen, aber das beantwortet die ursprüngliche Frage nicht.

Gäbe es einen gemeinsamen Subtyp Type1 und Type2SuperType genannt, dann sagen, dass der erste Typ ist ? extends SuperType funktionieren würde.

Hier ist ein kleines Beispiel, das Integer und Double wie die beiden Typen verwendet, und ihre gemeinsamen Vorfahren als Number:

private Map<Integer, String> doSomethingForInteger() { 
    HashMap<Integer, String> map = new HashMap<Integer, String>(); 
    map.put(10, "Hello"); 
    return map; 
} 

private Map<Double, String> doSomethingForDouble() { 
    HashMap<Double, String> map = new HashMap<Double, String>(); 
    map.put(3.14, "Apple"); 
    return map; 
} 

public Map<? extends Number, String> doSomething(boolean b) { 
    if (b) 
    return doSomethingForInteger(); 
    else 
    return doSomethingForDouble(); 
} 

Hier werden die doSomething Verfahren werden zwei Arten von HashMap s Rückkehr auf den boolean abhängig, die ist übergeben. Entweder HashMap<Integer, String> oder HashMap<Double, String> wird von der doSomething Methode zurückgegeben.

Eigentlich doSomething mit einem boolean Aufruf kann wie folgt erreicht werden:

Map<? extends Number, String> map1 = doSomething(true); 
Map<? extends Number, String> map2 = doSomething(false); 

map1 mit Hashmap<Integer, String> enden, während map2Hashmap<Double, String> bekommen.

+0

Ich schätze die Antwort, aber Sie haben es falsch herum. Ich möchte nicht, dass die Supertypemethode die öffentliche ist, und ich möchte, dass alle Instantmanisierungs-/Manipulationssachen nur in einer einzigen privaten Methode ausgeführt werden (dh keine Duplizierung davon). –

+0

Ups, tut mir leid, ich habe es durcheinander gebracht ... – coobird

0

Man könnte die Idee einer Schließung Modell:

interface MappingClosure { 
    public void map(Map, MapProvider); 
} 


class Caller implements MappingClosure { 
    public void map(final Map MAP, final MapProvider CALLEE) { 
     this.MAP = specialise(MAP); 
     // CALLEE USED AS KEY 
    } 
} 


class MapProvider { 
    public Map getMap(final MappingClosure CALLER) { 
     return CALLER.map(mapInstance, this); 
    } 
} 

dann die Daten Modifizieren der Objekte Bedürfnisse anpassen zu unterscheiden sind eine Methode mit dem ob ject, die es erfordert.

Verwandte Themen