Designfragen (mehrfach extends)

H2SO3-

Bekanntes Mitglied
Hi,

Hätte mal die Frage wie folgendes am besten gelöst werden kann. Die Frage geistert mir schon länger durch den Kopf. Es geht um mehrfach extends. Weiß zwar das dies in Java nicht möglich ist und bin generell auch zufrieden mit den erklärungen dennoch würde ich gerne wissen wie man folgendes gut machen kann.

Ich habe zwei basis klassen

Java:
public class Wasserbewohner{
      public void schwimmer(){
          // sehr komplexe methode zum schwimmen
      }
}

public class Lungenatmer{
       public void atmen(){
           // sehr komplexe methode um sauerstoff zu atmen
      }
}
aus diesen beidem classen möchte ich nun eine dritte erzeugen
Java:
public class Delphin extends Wasserbewohner, Lungenatmer{ }

Somit könnte mein Delphin sowohl schwimmen wie auch mit seinen Lungen atmen.
Da dies so in Java nicht geht, muss was anderes her.
Gehen würde es mit Interfaces. Jedoch müsste hier die Delphin klasse ja die beiden methoden schwimmen und atmen selber implementieren. Ist doof da Delphin genauso atmet wie alle anderen Lungenatmer und genauso schwimmen soll wie alle anderen Wasserbewohner.

Eine möglichkeit hierfür könnte folgendes sein. Aber besonders toll finde ich es nicht, jedoch hätte es den vorteil, das der code zentral liegt und von allen erweiterungen von Wasserbewohnern und Lungenatmern benutzt werden kann. Je nachdem was sie sind. Ein Pferd muss ja atmen aber nicht schwimmen genauso wie ein Hai schwimmen aber nicht atmen muss (halt nicht mit Lunge).


Java:
public interface Wasserbewohner{
      public void schwimmer();
}

public interface Lungenatmer{
       public void atmen();
}

public class Schwimmen{
      public static void schwimmen(){
          // sehr komplexe methode zum schwimmen
       }
}
public class Atmen{
       public static void atmen(){
           // sehr komplexe methode um sauerstoff zu atmen
      }
}
public class Delphin implements Wasserbewohner, Lungenatmer{ 
       public static void schwimmen(){
          Schwimmen.schwimmen();
       }
       public static void atmen(){
           Atmen.atmen();
      }
}

Hoffe mal hier kennt jemand eine gute Designidee. Bin mit sicherheit nicht der erste der sowas machen will.
 
M

maki

Gast
Interfaces & abstrakte Basisklassen, du hast übrigens das ideale Beispiel dafür gewählt, würde gern mal sehen wie du ein Platypus umsetzen wolltest mit deiner jetztigen Idee von extends ;)
 

H2SO3-

Bekanntes Mitglied
Bin mir nicht ganz sicher wie du das mit einer abstrakten basisklasse besser lösen willst. Eine alleine reicht ja auch hier wohl nicht.
Kannst du vielleicht ein minibeispiel geben.
Übrigens ein Platypus schwimmt doch genauso wie ein Fisch. (Zumind. wenn ich als Programierer es so definiere *gg*)

(Kann im moment nur selten ins netz also nicht wundern wenn die antwort etwas dauert)
 
M

maki

Gast
Abstrakte Basisklassen nur da wo es geht, ansonsten Interfaces.

Was du willst geht so nicht in Java, es gibt keine Mehrfachvererbung welche die Implementierung vererbt, nur die Schnitstellen, das ist ein Vorteil wenn man ihn man verstanden hat.

Ein Platypus hat einen Schnabel, Schwimmhäute, legt Eier in ein Nest auf dem trockenen, aber findet seine Nahrung im Wasser, wird offiziell als Säugetier geführt ;)

Interfaces bieten hier die flexibilität dass man bestimmte Eigenschaften bzw. Möglichkeiten getrennt definieren und trotzdem von ein und derselben Klasse implementieren lassen kann.
Ein extends impliziert dass viel mehr, eine "ist ein" Beziehung, Interfaces dagegen bedeutet ein "kann".

Vererbung ist nicht dafür da Code zu sparen oder Code wiederzuverwenden wo es "praktisch" aber nicht wirklich logisch ist, extends impliziert die stärkste Kopplung überhaupt.
Interfaces sind immer noch loser, Code lässt sich auch wiederverwenden bzw. Redundanz lässt sich vermeiden zB. durch delegation an Utility Methoden oder Klassen/Objekte die sich um spezifische Dinge kümmern, wie zB. das schwimmen.
 

Landei

Top Contributor
Theoretisch könnte man zwei Interfaces und zwei Klassen, die das Interface implementieren nehmen, und mittels DynamixProxy daraus eine Klasse zusammenschustern. Der InvocationHandler muss halt zwei Instanzen der implementierenden Klassen mitbekommen, und jeweils die Methodenaufrufe geeignet delegieren. Wäre aber ziemlich unschön, und hätte schlechte Performance. Mittels Bytecode-Manipulation ginge es bequemer.

Aber es stellt sich immer die Frage, ob man soetwas wirklich braucht, oder ob man sich nur beim Design nicht genügend Mühe gegeben hat.
 

DarkLegend

Mitglied
Hm noch nie wirklich damit zu tun gehabt, aber finde ich sehr interessant :D

Spontan würde bei mir sowas bei rauskommen: Quasi eine Kombination von abstrakten Klassen und Interfaces.

Java:
public abstract WasserLebewesen {
    public SauerStoffOrgan sauerStoffOrgan;
    public WasserFortbewegung fortbewegung;

    public Lebewesen( SauerStoffOrgan sso, WasserFortbewegung wf) {
       [...]
    }

    public void schwimmen() {
       fortbewegung.schwimmen();
    }

    public void atmen() {
       sauerStoffOrgan.atmen();
    }
}

public interface WasserFortbewegung{
      public void schwimmen();
}
 
public interface SauerStoffOrgan{
       public void atmen();
}
 
public class Schwimmen implements WasserFortbewegung{
      public void schwimmen(){
          // sehr komplexe methode zum schwimmen
       }
}
public class Lunge implements SauerStoffOrgan{
       public void atmen(){
           // sehr komplexe methode um sauerstoff zu atmen
      }
}
public class Delphin extends WasserLebewesen{ 
      public Delphin() {
          super(new Lunge(), new Schwimmen() );
      }
}
 

Landei

Top Contributor
Es heißt ja immer "Komposition statt Vererbung". Trotzdem bleibt das Problem, dass dein Delphin die anderen Interfaces nicht implementiert, also nicht an deren Stelle verwendet werden kann - was je nach Design das ganze wenig nützlich werden läßt.
 

DarkLegend

Mitglied
stimmt... den Aspekt an der Sache habe ich noch garnicht gesehen ;) Wobei man dem Wasserlebewesen die Interfaces eigentlich auch mitgeben könnte...
 
H

Herr K.

Gast
Hallo H2SO3-,

Dein Ansatz ist soweit eigentlich korrekt. An sich kannst Du hier einfach den Aufruf delegieren. Allerdings sollten die Klassen Schwimmen und Atmen die zugehörigen Interfaces implementieren. Damit stellst Du sicher, dass die Signatur und der Rückgabewert konsistent zu Änderungen am Interface gehalten werden (und Du kannst sinnvoll in der Dokumentation auf eben diese Methode verweisen).

Um Dein Leben etwas zu vereinfachen könntest Du als nächstes auf DI (Depency Injection) setzen und Dir die jeweilige Implementierung injezieren lassen (losere Kopplung), alternativ eine Fabrik verwenden, welche Dir eben die Standardimplementierung respektive ein Exemplar der Standardimplementierung zurück gibt.

Hast Du nun auch noch eine Sammlung von Meeressäugern, dann bietet sich hier eine abstrakte Basisklasse an, welche eben die beiden Interfaces implementiert und damit auch die Delegation vereinheitlicht.

Desweiteren solltest Du prüfen, ob Du Dein Objektdesign anpassen solltest. Du beschränkst Dich hier sehr stark auf die Vererbung um ein bestimmtes Verhalten wiederzuverwenden. Das Ziel der Vererbung liegt aber vor allem in der Abstraktion und Austauschbarkeit.
Ein Lungenatmer klingt hier etwas zu speziell. Ohne nähere Kenntnis der Fachlichkeit würde ich sagen, dass sich eher ein Interface "Atmer" anbietet und eben die Implementierungen Lungenatmer, Hautatmer und Kiemenatmer (oder was es sonst so gibt) festlegen wie die Methode "atmen()" genau implementiert wird.

Hier kann es sich dann anbieten, dass Du einfach auf Atmen und Fortbewegen als Interfaces abstrahierst und verschiedene Basisimplementierungen anbietest (für Atmen hatten wir das schon, für das Fortbewegen dann eben schwimmen, laufen und fliegen).
Jedes Lebewesen hat nun jeweils eine Art zu atmen und eine sich fortzubewegen. In dem Fall kannst Du dann auch die Delegation in eine Basisklasse stecken:
Java:
public interface IAtmen {
  public void atmen();
}

public interface IBewegen {
  public void bewegen();
}

public abstract class Lebewesen implements IAtmen, IBewegen {
  private IAtmen atmen;
  private IBewegen bewegen;
  
  public void setAtmen(IAtmen atmen) {
    this.atmen = atmen;
  }
  
  public void setBewegen(IBewegen bewegen) {
    this.bewegen = bewegen;
  }
  
  public void bewegen() {
    if (this.bewegen == null) {
      throw new InitializationException("...");
    }
    
    this.bewegen.bewegen();
  }
  
  public void atmen() {
    if (this.atmen == null) {
      throw new InitializationException("...");
    }
    
    this.atmen.atmen();
  }
}

Zu den Interfaces kannst Du jetzt jeweils eigene Implementierungen erzeugen, ich sage einfach mal es gibt LungenAtmer und KiemenAtmer, sowie die Flieger und die Schwimmer. Eine Klasse Fisch (Schwimmer und Kiemenatmer) kann jetzt von der Basisklasse Lebewesen abgeleitet werden, wobei sichergestellt werden muss, dass die Implementierungen über die Setter implementiert werden. Hierbei kannst Du auf das Builderpattern zurückgreifen:
Java:
public class LebewesenBuilder {
  private Lebewesen lebewesen;

  public LebewesenBuilder(final Lebewesen lebewesen) {
    this.lebewesen = lebewesen;
  }

  public LebewesenBuilder setLungenatmer() {
    this.lebewesen.setAtmer(new LungenAtmer());
    return this;
  }

  public LebewesenBuilder setKiemenatmer() {
    this.lebewesen.setAtmer(new KiemenAtmer());
    return this;
  }

  public LebewesenBuilder setSchwimmer() {
    this.lebewesen.setBewegen(new Schwimmer());
    return this;
  }

  public LebewesenBuilder setFlieger() {
    this.lebewesen.setBewegen(new Flieger());
    return this;
  }

  public Lebewesen build() {
    return this.lebewesen;
  }
}

Jetzt kannst Du die Implementierungen sehr einfach im Konstruktor der jeweiligen Implementierung vornehmen.
Java:
public class Fisch extends Lebewesen {
  public Fisch() {
    new LebewesenBuilder(this).setSchwimmer().setKiemenatmer();
  }
}

public class Vogel extends Lebewesen {
  public Fisch() {
    new LebewesenBuilder(this).setFlieger().setLungenatmer();
  }
}
 

Noctarius

Top Contributor
Man kann auch häufig genutzt Implementierungen in Utility-Klassen auslagern und dann in den implementierenden Klassen aufrufen.

Java:
public class AtemUtils {
  private AtemUtils() { }

  public static void atem(Atem atem) {
    atem.atmen();
  }
}

public class Delphin extends Wasserbewohner, Lungenatmer{
  private final Atem atem = new Atem();

  public void atmen() {
    AtemUtils.atmen(atem);
  }
}

So braucht man gleiche Implementierungen nicht mehrfach kopieren. Code-Doppler sind auch unschön :)
 
H

Herr K.

Gast
@Noctarius:
So wie bereits im ersten Post enthalten? Die Frage zielt ja gerade darauf ab, ob man das nicht schöner machen kann...
 
Ähnliche Java Themen
  Titel Forum Antworten Datum
D next() Methode mehrfach verwenden Java Basics - Anfänger-Themen 1
F Session wird mehrfach erzeugt Java Basics - Anfänger-Themen 11
W Mehrfach das gleiche Attribut für ein Objekt erzeugen (mit verschiedenen Werten) Java Basics - Anfänger-Themen 2
KopaCoda Getter mehrfach aufrufen -> ist das guter code? Java Basics - Anfänger-Themen 3
S Vererbung Java mehrfach Java Basics - Anfänger-Themen 10
kokojamboo92 char mehrfach ausgeben.. Java Basics - Anfänger-Themen 2
U Mehrfach verwendete Sub-Klassen richtig einbinden Java Basics - Anfänger-Themen 4
J Array innerhalb einer Funktion mehrfach iniatilisieren Java Basics - Anfänger-Themen 4
L Mit java ein wort mehrfach versetzt darstellen Java Basics - Anfänger-Themen 14
L LinkedList Comparable < > MEHRFACH implementieren? Java Basics - Anfänger-Themen 3
C Mehrfach Array "speichern" Java Basics - Anfänger-Themen 9
D Erste Schritte Countdown mehrfach verwenden Java Basics - Anfänger-Themen 5
A String Mehrfach Splitten Java Basics - Anfänger-Themen 1
R JUnit Test mit mehrfach ausgeführt Java Basics - Anfänger-Themen 6
J Objekterzeugung im Konstruktor - Mehrfach gleiche Referenzvariable? Java Basics - Anfänger-Themen 4
T Mehrfach auftretende Zahlen in einem Array Java Basics - Anfänger-Themen 13
P RegEx Muster mehrfach treffen Java Basics - Anfänger-Themen 2
T methode mehrfach automatisch ausfuehren Java Basics - Anfänger-Themen 6
S Objekt mehrfach erzeugen Java Basics - Anfänger-Themen 3
M mehrfach auftretende zahlen in einem array Java Basics - Anfänger-Themen 6
0 Exceptions mehrfach fangbar? Java Basics - Anfänger-Themen 4
W mehrfach parameterized Java Basics - Anfänger-Themen 4
? java.util.Properties Wert von key mehrfach vorhanden Java Basics - Anfänger-Themen 13
M Applikation darf nicht mehrfach gestartet werden Java Basics - Anfänger-Themen 2
N Mehrfach von Klassen benutze Methode in Interface auslagern? Java Basics - Anfänger-Themen 3
S Combobox mehrfach verwenden Java Basics - Anfänger-Themen 3
H Wie Consolen Application mehrfach duchlaufen lassen? Java Basics - Anfänger-Themen 10
H Mehrfach in eine Datei schreiben, wie geht das? Java Basics - Anfänger-Themen 6
S ArrayList mehrfach Java Basics - Anfänger-Themen 4
G String mehrfach ausgeben Java Basics - Anfänger-Themen 5
mrStudent <? extends T> und <? super T> Java Basics - Anfänger-Themen 1
berserkerdq2 Größter unterschied von extends thread und implements runnable? Java Basics - Anfänger-Themen 2
N Variabel in eine class mit "extends JLabel" übertragen Java Basics - Anfänger-Themen 2
J extends Problem Java Basics - Anfänger-Themen 2
N extends und super vs new object Java Basics - Anfänger-Themen 4
JavaTalksToMe Extends/Implements Frage Java Basics - Anfänger-Themen 3
D public ArrayList(Collection<? extends E> c); Java Basics - Anfänger-Themen 2
CptK Interface Klasse Frame (extends JFrame) aus anderer Klasse schließen Java Basics - Anfänger-Themen 7
J Implements und Extends Java Basics - Anfänger-Themen 5
C Was macht `public class ClassName<T extends Comparable<T>>`? Java Basics - Anfänger-Themen 14
J Compiler-Fehler Fehler bei Vektor (E extends Object declared in class Vector) Java Basics - Anfänger-Themen 9
M mehrere extends? Java Basics - Anfänger-Themen 19
J doppelname nach schlüsselwort extends Java Basics - Anfänger-Themen 4
V Was bewirkt das Schlüsselwort extends in Verbindung mit class bzw. public class ? Java Basics - Anfänger-Themen 2
T extends und implements Java Basics - Anfänger-Themen 11
Crazynet 2 extends Java Basics - Anfänger-Themen 22
S Wrapper Klasse und extends Java Basics - Anfänger-Themen 2
W Methoden Rückgabedatentyp java.util.Map<java.lang.String,? extends ...> Java Basics - Anfänger-Themen 4
R Vererbung Übergabe von Variablen der Superklasse an Subklasse mit "extends" Java Basics - Anfänger-Themen 5
K Erste Schritte Extends Implements Java Basics - Anfänger-Themen 4
S Threads Thread wenn extends schon vergeben Java Basics - Anfänger-Themen 8
vandread Java Wildcards - Wann super wann extends? Java Basics - Anfänger-Themen 2
F Anfängerfrage zu extends Java Basics - Anfänger-Themen 12
B addAll(Collection<? extends E> c) Java Basics - Anfänger-Themen 9
T Input/Output StructuredFileReader extends BufferedReader Java Basics - Anfänger-Themen 6
K Erste Schritte extends vererbung Java Basics - Anfänger-Themen 15
P Class<? extends Entity> Array Java Basics - Anfänger-Themen 9
A final und extends Java Basics - Anfänger-Themen 14
Y Threads extends Thread oder implements Runnable Java Basics - Anfänger-Themen 10
C Vererbung "extends" umgehen mittels Objekterzeugung?! Java Basics - Anfänger-Themen 29
L Implements<-->extends und Interface Java Basics - Anfänger-Themen 10
T Collections Queue<? extends Number> add() offer() Java Basics - Anfänger-Themen 13
S Klasse extends HashMap Java Basics - Anfänger-Themen 20
L Problem mit Vererbung (extends) cannot find symbol Java Basics - Anfänger-Themen 3
D MyActionListener extends Thread Java Basics - Anfänger-Themen 3
G Unterschied e extends y vs ? extends y Java Basics - Anfänger-Themen 5
X List von Klasse B als List von Klasse A (B extends A) Java Basics - Anfänger-Themen 2
H extends Locale Java Basics - Anfänger-Themen 4
O import ja....extends nein Java Basics - Anfänger-Themen 5
G Muss es immer extends sein ? Java Basics - Anfänger-Themen 9
N class Test<E extends MyAbstractClass> => typ von E? Java Basics - Anfänger-Themen 5
K mehrere Extends Java Basics - Anfänger-Themen 2
S extends Vector<xyz> Java Basics - Anfänger-Themen 10
S new .() extends JDialog {.} Java Basics - Anfänger-Themen 15
S extends und Konstruktor Java Basics - Anfänger-Themen 8
E Interface extends Observable Java Basics - Anfänger-Themen 13
G Wiedermal vererbung, extends JDialog extends Exception ? Java Basics - Anfänger-Themen 8
U extends JLabel & Thread Java Basics - Anfänger-Themen 2
G Innere klasssen unde "extends" klassen definieren, Java Basics - Anfänger-Themen 2
frau-u JMenu mit extends JPanel? Java Basics - Anfänger-Themen 4
G "extends DBConnection" funktioniert nicht Java Basics - Anfänger-Themen 15
N extends / implements / static, bedeutung ?? Java Basics - Anfänger-Themen 12
C Problem mit Zeichnen auf einer extends Canvas Class... Java Basics - Anfänger-Themen 2

Ähnliche Java Themen

Neue Themen


Oben