Überladung

Sadret

Mitglied
Hallo,

ich habe ein Interface Interf und mehrere Klassen A, B, C, die alle dieses Interface implementieren.

In einer anderen Klasse nehme ich in einer Methode eine Instanz von Interf an und möchte mit diesem Objekt weiterarbeiten, und zwar abhängig von der eigentlichen Klasse. Mein erster Ansatz war:

Java:
void foo(Interf i){
	//default
	syso("default");
}

void foo(A a){
	//do sth. with a
	syso("a");
}

void foo(B b){
	//do sth.with b
	syso("b");
}

void foo(C c){
	// do sth. with b
	syso("c");
}

Dummerweise wird bei einem Aufruf von foo immer foo(Interface i) ausgeführt:

Java:
foo(new A());
Output: "default"


Mein nächster Ansatz funktioniert zwar, ist aber umständlich:

Java:
void foo(Interface i){
	if(i instanceof A)
		foo((A) i);

	if(i instanceof B)
		foo((B) i);

	if(i instanceof C)
		foo((C) i);
}

void foo(A a){
	//do sth. with a
	syso("a");
}

void foo(B b){
	//do sth.with b
	syso("b");
}

void foo(C c){
	// do sth. with b
	syso("c");
}

Gibt es da eine elegantere Lösung? Wenn neue Klassen dazu kommen, die Interf implementieren, muss man halt immer an mehreren Stellen den Code ändern.
Ich kann leider die Klassen A, B, C, und das Interface nicht ändern (sonst wäre das alles kein Problem).
 

fischefr

Aktives Mitglied
Code:
void foo(Interface i){
    if(i instanceof A)
        foo((A) i);
 
    if(i instanceof B)
        foo((B) i);
 
    if(i instanceof C)
        foo((C) i);
}

Die Methode ist ziemlicher Mist. Was machst du, wenn das Argument zwar das Interface implementiert, aber weder eine Instanz von A, B noch C ist? Die Logik sollte in dieser Methode stehen und foo(A a), foo(B b) u.s.w. die Methode foo(Interface i) aufrufen - nicht andersrum. Wenn das nicht geht, stimmt etwas mit deiner Vererbung nicht!
 

Sadret

Mitglied
Natürlich ist das Mist, aber weißt du was besseres? Solche Antworten kannst du dir in Zukunft auch sparen.

Die Logik sollte in dieser Methode stehen und foo(A a), foo(B b) u.s.w. die Methode foo(Interface i) aufrufen - nicht andersrum.
Und was meinst du damit? Wie soll in foo(Interface i) die Logik stehen, wenn man je nach Klasse unterschiedliche Sachen vorhat?
 
T

tummo

Gast
Von Sinn und Praxisrelevanz solcher Aufgaben mal abgesehen:
Java:
public class Foo {

	private final Map<Class<?>, String> messages = new HashMap<>();
	{
		messages.put(A.class, "a");
		messages.put(B.class, "b");
		messages.put(C.class, "c");
		// ...
	}

	private String getMessage(Class<?> clazz) {
		for (Entry<Class<?>, String> entry : messages.entrySet()) {
			if (entry.getKey().isAssignableFrom(clazz)) {
				return entry.getValue();
			}
		}
		return "default";
	}

	public void foo(Interf i) {
		System.out.println(getMessage(i.getClass()));
	}

}
Java:
public class Main {

	public static void main(String[] args) {
		Foo foo = new Foo();
		foo.foo(new A());
		foo.foo(new B());
		foo.foo(new C());
		foo.foo(new Interf() {
		});
	}

}
Ausgabe:
Code:
a
b
c
default
Wenn der Code der foo-Methode über "einen String ausgeben" hinausgeht, musst du dies natürlich in eigenen Objekten kapseln und den Code anpassen. Das wäre aber nur eine geringfügige Änderung.
 
Zuletzt bearbeitet von einem Moderator:

Sadret

Mitglied
Etwas umständlich, da es wirklich auf etwas mehr als nur Strings ausgeben hinausläuft, aber trotzdem ein interessanter Ansatz.
 

Sen-Mithrarin

Gesperrter Benutzer
ich glaube hier hast du irgendwas verdreht

warum willst du denn sowas wie

do(Interface)
do(ImplA)
do(ImplB)

machen, wenn du das ganze auch ins interface stecken kannst

interface Blub{
do();
}

und dann den krams in die implementierungen steckst

dann kannst du bequem in der klasse bloß noch

Interface.do();

callen und die jeweilige implementierung wird ausgeführt


ich glaub du hast interfaces irgendwie falsch verstanden
 

Sadret

Mitglied
Nein, ich habe Interfaces nicht falsch verstanden. Lest doch einfach mal die Frage: ich habe das Interface und die Klassen gegeben und kann diese nicht ändern.
 

Sen-Mithrarin

Gesperrter Benutzer
dann hat derjenige der dir die aufgabe gegeben hat was nicht verstanden ... weil SO ist das eher ein fall für generics ...



weil man mit einem interface grundsätzlich so arbeitet das man halt im interface methoden vorgibt, diese dann durch die implementierungen füllt ... und dann im caller gegen das interface arbeitet

im caller spezielle methoden für einzelne implementierungen macht keinen sinn ... dann braucht man kein interface sondern kann direkt gegen die einzelnen klassen arbeiten ...

und DAS ist sicher nicht der sinn von interfaces ... das geht wie gesagt schon eher richtung generics
 

Sadret

Mitglied
Das ist keine Aufgabe, das ist aus der Praxis entstanden.

Wie schwer ist es denn eigentlich zu verstehen, dass die Klassen gegeben sind und ich sie einfach nicht ändern kann?

Ich habe ein fertige Bibliothek, die ich benutze, und in meinem Projekt arbeite ich mit deren Klassen und Interfaces.
Daher ist auch überhaupt nichts am Design der Klassen verkehrt, weil diese komplett unabhängig von meinem Projekt sind.
 

Sen-Mithrarin

Gesperrter Benutzer
es ist kein problem zu rallen das der schrott so gegeben ist ... aber so verwendet man interfaces schlicht und einfach nicht

anderes beispiel

interface : Fahrzeug
implementierungen : Auto, Trident2-Trägerrakete
methoden : start, beschleunigen

wenn ich jetzt deinen code nehmen würde hätte ich sechs methoden, jeweils zwei für das interface Fahrzeug selbst, zwei fürs auto und zwei für die rakete

da sowohl das auto als auch die rakete das interface implementieren und man nach most-abstract geht wird grundsätzlich immer nur die methode für fahrzeuge allgemein aufgerufen, nicht die anderen beiden
und die muss dann selbst wieder auseinanderziehen um was für ein fahrzeug es sich handelt ...
das ist aber NICHT die aufgabe DEINES codes, sondern der implementierung selbst !

korrekt wäre also : man hat ein objekt was Fahrzeug implementiert und callt darauf die methoden, die dann von der implementierung ausgeführt werden


wie gesagt : der code den du da gegeben hast ist 1A schrott ... weil man so einfach nicht mit interfaces umgeht ... die lib will ich mir mal geben ...
 

KSG9|sebastian

Top Contributor
Vielleicht bietet die Lib mit Absicht dafür keine Funktion im Interface an? Vll. sind es Methoden welche absichtlich nur der Implementierung bekannt sind?!

Arbeitet ihr mit Spring? Dann würde ich versuchen mittels Proxies da eine einheitliche Schicht darüber zu ziehen. Dann definierst du quasi ein eigenes Interface und verkettest mittels Spring so das du am Interface nur eine Methode aufrufst und Spring per Konfiguration entscheidet was konkret auf der Implementierung aufgerufen werden soll.
 

Sadret

Mitglied
@Sen-Mithrarin

Du sagst zwar, dass du verstanden hast, dass die Klassen gegeben sind, aber deine Antwort zeigt anderes.

Vielleicht verstehst du es besser, wenn ich dein Beispiel benutze.

gegeben:
Das Interface Fahrzeug mit den Methoden start() und beschleunigen() und die Klassen Auto und Rakete, die das Interface jeweils implementieren.

Was gemacht werden muss:
Ein Lackierer bietet an, jedes mögliche Fahrzeug zu lackieren. Dafür hat er eine Methode lackiere(Fahrzeug f). Je nach Fahrzeug (z.B. Auto oder Rakete) muss er natürlich andere Sachen machen. Wie würdest du das jetzt implementieren? Der Lackierer hat logischerweise keine Möglichkeit, die Klassen Auto oder Rakete zu ändern und die Hersteller von Auto und Rakete haben mit dem lackieren nichts zu tun, also werden sie die Methode Fahrzeug.lackieren() (bzw. Auto.lackieren() & Rakete.lackieren()) auch nicht selber implementieren.
 
Zuletzt bearbeitet:

Sadret

Mitglied
@KSG9|sebastian

Ja, die Methoden werden "absichtlich" nicht im Interface deklariert, da sie den Machern des Interfaces völiig unbekannt und für sie irrelevant sind.

Ich benutze allerdings kein Spring.
 

Ähnliche Java Themen

Neue Themen


Oben