Vererbung Vererbung, Interfaces und OOP...

Vulpecula

Mitglied
Hallo zusammen! Ich habe mal ein paar konkrete Fragen in Sachen Vererbung und Objektorientierung. Und zwar geht es in einer Aufgabe darum, den Vierecken in der Abbildung eine hierarchische Struktur zuzuweisen:



Das Bild habe ich aus der Wikipedia und habe auch direkt schon mit Pfeilen eine Hierarchie deutlich gemacht.

Mein Plan ist jetzt, die Klasse Viereck als abstrakte Klasse zu formulieren und dann die Klassen darunter davon Erben zu lassen. Hier komme ich aber bereits ins straucheln.

  1. Als Methoden möchte ich je Körper erstmal die Formeln für Fläche und Umfang implementieren. Da ich allerdings unterschiedliche Formeln benötige, ist ja auch jedes Mal die Signatur des Konstruktors eine andere. Ich könnte mit mehreren Konstruktoren arbeiten, aber muss ich dann in JEDER (ver)erbenden Klasse den selben Haufen Konstruktoren ausformulieren? Was wäre die eleganteste Art, um das Problem zu lösen?
  2. In der Abbildung wird ja deutlich, dass Quadrat seine Eigenschaften sowohl vom Rhombus als auch vom Rechteck erbt. Mehrfachvererbung ist in Java ja nicht möglich, daher liegt die Verwendung eines Interface nahe. Wie würde das in diesem Fall zur Anwendung kommen? (Bzw.: Wie würde man Interfaces generell bei Fällen einsetzen, wo ansonsten eine Mehrfachvererbung bestehen würde?)

MfG - Vulpecula
 
Zuletzt bearbeitet:
Du hast es mit den Interfaces erfasst. Definiere Interfaces dafür und überlass die Konstruktion den implementationen. best practice wäre natürlich ein Interface Viereck und den Rest als Vererbungsbaum zu ralisieren. Da du aber im Java nur von einer Klasse erben kannst, geht das in Java nicht.
 
Etwas zu vererben macht nur Sinn wenn zwei Objekte etwas gleich haben. (Eigenschaft od. Methode)
Außer den vier Ecken sehe ich hier keine Gemeinsamkeiten.
Was willst du hier vererben, bzw. wo ist hier eine Hierachie?
Jede Form hat seine Eigenheiten.
 
Naja, es gibt schon Gemeinsamkeiten... Für ein abstraktes Viereck gilt ja z.B.: vier Seiten/Ecken, zwei Diagonale, Fläche, Umfang. Das sind ja schonmal Eigenschaften, die für ALLE Vierecke gelten, egal ob es sich dabei um ein Trapez oder ein konv. Viereck handelt. Die Methode zur Berechnung der Fläche kann ich ja z.B. durch die abstrakte Klasse erzwingen und in den einzelnen, vererbten Klassen überschreiben.
Dazu kommt, dass zwar jede Form Eigenheiten hat, aber ein Quadrat ist. z.B. auch eine Art Rechteck, welches wiederum eine Art von Parallelogramm ist, usw... Mag sein, dass sich die Formeln ändern, aber an der Tatsache, dass Gemeinsamkeiten bestehen, ändert das nichts.
 
Zuletzt bearbeitet:
Etwas zu vererben macht nur Sinn wenn zwei Objekte etwas gleich haben. (Eigenschaft od. Methode)
Außer den vier Ecken sehe ich hier keine Gemeinsamkeiten.
Was willst du hier vererben, bzw. wo ist hier eine Hierachie?
Jede Form hat seine Eigenheiten.

Da wären z.B. Dinge wie Kantenlänge gegenüberliegender Seiten, Winkelsumme, Umfang, Mittelpunkt etc. Wenn man diese Eigenschaften betrachtet lassen sich schon sinnvolle Gruppen erstellen. Aber z.B. das hier ist leider nicht möglich:
Java:
class Shape
{
    protected int[] bounds = new int[]; // n seiten
    protected int[] angles = new int[]; // n seiten

    public final int getNumSides()
    {
        return bounds.length;
    }
    public void setBounds(int... bounds)
    {
        if (bounds.length != this.bounds.length)
        {
            throw new IllegalArgumentException("Too many/few new bounds");
        }
        this.bounds = bounds;
    }
    public void setAngles(int... angles)
    {
        if (angles.length != this.angles.length)
        {
            throw new IllegalArgumentException("Too many/few new angles");
        }
        this.angles = angles;
    }
}
class Viereck extends Shape
{
    public Viereck()
    {
        bounds = new int[4]; // 4 seiten
        angles = new int[4]; // 4 seiten
    }

    public setBounds(int a, int b, int c, int d)
    {
        this.bounds[0] = a;
        this.bounds[1] = b;
        this.bounds[2] = c;
        this.bounds[3] = d;
    }
    public setAngles(int a, int b, int c, int d)
    {
        if (a + b + c + d != 360)
        {
            thow new DefinitionException("Die Winkelsumme im Viereck ist immer 360°");
        }
        this.angles[0] = a;
        this.angles[1] = a;
        this.angles[2] = a;
        this.angles[3] = a;
    }
}
class Quadrat extends Rechteck, Raute
{
    // keine Implementierung nötig, die Eigenschaften aus Parallelogramm, Rechteck und Raute
    // kombiniert reichen aus
}
class Parallelogramm extends Viereck
{
    public void setBounds(int a, int b, int c, int d)
    { // ab dem parallelogramm sind sich gegenüberliegende seiten immer gleich
        if (a != c || b != d)
        {
            throw new DefinitionExcetpion("Gegenüberliegende Seiten sind im Parallelogramm gleich.");
        }
        super(a, b, a, b);
    }
}
class Raute extends Parallelogramm
{
    public void setBounds(int a, int b, int c, int d)
    { // ab der Raute sind alle seiten gleich
        if (a != b || a != c || a !=d)
        {
            throw new DefinitionExcetpion("In der Raute sind alle Seiten gleich.");
        }
        super(a, a, a, a);
    }
}
class Rechteck extends Parallelogramm
{
    public void setAngles(int a, int b, int c, int d)
    {
        if (a != 90 || b != 90 || c != 90 || d != 90)
        {
            throw new DefinitionException("Im Rechteck sind alle Winkel = 90°");
        }
        super(90);
    }
}
 
Zuletzt bearbeitet:
Mehrfachvererbung ist in Java nicht möglich. Auf Interfaces würde ich aber nur bei unabhängigen Klassen zurückgreifen. In diesem Fall beschreibt ein Parallelogramm die drei Klassen Rechteck, Raute und Quadrat komplett.
 
Der Fehler liegt hier in der Logik und damit bereits im Modell.
Hier will man mit Vererbung etwas abbilden, was kein Fall von Vererbung ist.

(1) Zunächst einmal zum Begriff "Eigenschaften".
Es ist besser den Begriff "Attribute" zu verwenden. Warum?

Welche Attribute beschreiben ein Viereck?
Welche Attribute beschreiben ein Trapez?

Man wird feststellen, es sind dieselben.

Die "Eigenschaft", dass ein Trapez zwei parallele Seiten hat ist kein beschreibendes Attribut. Man würde es ggf. als Methode isTrapez() implementieren, die berechnet, ob das Viereck zwei parallele Seiten hat und daher ein Trapez ist und TRUE oder FALSE zurückliefern.

"Eigenschaften" umfassen somit "Methoden" und "Attribute" !!
Das ist eine wichtige Erkenntnis beim Modellieren.

(2)
Bei der Modellierung von Klassen sind zunächst die Attribute entscheidend, welche die Instanzen der Klasse beschreiben. Nicht alles, was andere Eigenschaften hat wird als eigene Klasse implementiert. So sind Asiaten und Europäer keine eigenen Unterklassen einer Klasse Mensch, sondern die Attribute mit denen sie beschrieben werden sind gleich. Obwohl Asiaten eine besondere Eigenschaft haben (z.B. Mandelaugen oder immer schwarzes Haar) rechtfertigt das keine eigene Klasse und damit auch keine Vererbung von der Klasse Mensch.
Hier könnte ggf. ein Attribut "Rasse" in der Klasse Mensch zur Unterscheidung implementiert werden.


(3)
Vererbung in der OOP und insbesondere in Java zielt auf "Erweiterung" (--> extends !!) einer bestehenden Klasse ab. Die Oberklasse muss also um Attribute oder Methoden erweitert werden, die in der Oberklasse selbst keinen Sinn machen würden. Es geht also um Spezialisierung auf der einen und Abstraktion auf der anderen Seite.

(4)
Mehrfachvererbung ist sehr problematisch. Wenn z.B. beide geerbten Klassen die gleiche Methodensignatur verwenden, wäre unklar, welche aufgerufen werden soll. Noch problematischer wird es wenn Attribute mehrfach vererbt werden. Daher haben die Entwickler von Java wohlweislich darauf verzichtet. Es gibt keine Mehrfachvererbung, jedoch eine Mehrfachtypisierung

(5)
Mehrfachtypisierung wird über Interfaces implementiert. Über die definierten Methodensignaturen einigen sich die implementierenden Klassen darauf, eine vorgegebene Methode zu implementieren. Damit "erbt"eine Klasse gewissermaßen einen bestimmten Typ. Da eine Klasse mehrere Interfaces implementieren kann, kann dadurch eine Klasse unterschieldlichen Typen angehören.


Gruß
JP
 
Mehrfachtypisierung wird über Interfaces implementiert. Über die definierten Methodensignaturen einigen sich die implementierenden Klassen darauf, eine vorgegebene Methode zu implementieren. Damit "erbt"eine Klasse gewissermaßen einen bestimmten Typ. Da eine Klasse mehrere Interfaces implementieren kann, kann dadurch eine Klasse unterschieldlichen Typen angehören.

Hier habe ich anscheinend noch Verständnisprobleme. Wenn also über Interfaces eine Art "Typisierung" stattfindet, ist diese aber rein informeller Natur, oder? Soll heißen: Bestimmte Features der Vererbung würden dadurch verloren gehen, wie z.B. die Vererbung von Attributen und/oder Methoden und diese müssten in der Klasse auf jeden Fall neu implementiert werden (sofern dies nich eh schon durch das Interface erzwungen wird).

Irgendwie verstehe ich die Vererbungs-Geschichte noch nicht so ganz. Überall liest man, dass es besser ist, so wenig wie möglich zu vererben und stattdessen Interfaces zu benutzen, nur warum wird diese Funktionalität dann geboten? Außerdem wird diese Aufgabe mit den Vierecken immer frustrierender, je länger ich darüber brüte. Im Moment weiß ich jedenfalls nicht, wie ich da weitermachen soll.
:bahnhof:
 
Vererbung ist gut, allerdings wird es zu oft mißbraucht für Dinge für die es nicht gedacht ist.

Deine Idee mit der Vererbung funktioniert zwar, bricht aber genau genommen die Regeln von Vererbung.

Wie schon geschrieben bedeutet Vererbung eine Erweiterung. Bestehende Funktionen der Superklasse müssen weiterhin gleich funktionieren.

Nun gibt es das Paradebeispiel dafür:

Java:
class Rechteck {
   setSeite(int seiteA, int seiteB) { this.a = seiteA; this.b = seiteB; }
}

class Quadrat extends Rechteck{
   setSeite(int seiteA, int seiteB) { if(seiteA != seiteB) throw new IllegalArgumentException("a muss gleich b sein"); super.setSeite(seiteA, seiteB); }
}

Ganz einfacher Code..Klasse Rechteck definiert eine Methode um die Seiten a und b zu setzen. Beim Rechteck gibt es keine Einschränkung.

Nun gibt es einen Subtyp Quadrat welcher sagt: "die Seiten müssen gleichlang sein, sonst ist es kein Quadrat". Mit dieser Einschränkung sind die Richtlinien für Vererbung schon gebrochen.

Dadurch ändert man nämlich bestehende Funktionalität der Superklasse - man schränkt die Funktionalität ein anstatt sie zu erweitern.

Mann kann es auch als Haarspalterei sehen, aber gerade im Bereich Frameworkentwicklung sind solche Dinge sehr, sehr übel.

Hat ein verwender nun einfach eine Liste von Rechtecken und eine Funktion "alle Seiten auf a=2, b=3" setzen, dann bekommt er eine Exception. Anschließend wird er in der Schleife instanceof-Abfragen einbauen und somit ist die Vererbung mehr oder weniger wieder ausgehebelt.

Interfaces sind eine gute Lösung für dein Problem.

Interfaces beschrieben nur welchen Vertrag eine Klasse erfüllen muss. Wie die Implementierung aussieht ist dem Interface (und eigentlich auch dem Verwender) egal. Bei Interfaces geht auch "Mehrfachvererbung".
 
Zuletzt bearbeitet:
Da wären z.B. Dinge wie Kantenlänge gegenüberliegender Seiten, Winkelsumme, Umfang, Mittelpunkt etc.

Das kommt sehr darauf an, was man unter einem Mittelpunkt versteht. Einen Umkreismittelpunkt besitzen nur Sehenvierecke, hier nur Quadrat und Rechteck, bzw ein gleichschenkliges Trapez.
Inkreismittelpunkt besitzten nur Tangtenvierecke, hier nur Quadrat und Rombus, eventuell eine spezialfrom des Trapez.
Mittelpunkt als Schnittpunkt der Diaogonalen, geht bei konkaven Vierecken nicht gut auf, da der Schnittpunkt dort außerhalb des Vierrecks liegt und damit irgentwie nicht mehr so richtig in der Mitte.
 
Das kommt sehr darauf an, was man unter einem Mittelpunkt versteht. Einen Umkreismittelpunkt besitzen nur Sehenvierecke, hier nur Quadrat und Rechteck, bzw ein gleichschenkliges Trapez.
Inkreismittelpunkt besitzten nur Tangtenvierecke, hier nur Quadrat und Rombus, eventuell eine spezialfrom des Trapez.
Mittelpunkt als Schnittpunkt der Diaogonalen, geht bei konkaven Vierecken nicht gut auf, da der Schnittpunkt dort außerhalb des Vierrecks liegt und damit irgentwie nicht mehr so richtig in der Mitte.

Ist schon klar. Was spricht gegen eine
Code:
InformationNotAvailableException
?
 

Zurück
Oben