Klassen Vererbung und zusätzliche Unterklassen

alex9090

Mitglied
Hallo ich habe folgende Aufgabenstellung:
  • Rectangle.java:
    • Subklasse von Shape.
    • erbt double-Werte xOrigin und yOrigin aus der Klasse Shape und speichert zusätzlich zwei double-Werte xDelta und yDelta, die die Hälfte einer Seitenlänge des Rechteckes in x- oder y-Richtung darstellen.
    • Initialisierung erfolgt im Konstruktor der Klasse Rectangle, der den Konstruktor der Superklasse aufruft.
    • die Klasse enthält eine circumference-Methode, die den Umfang des Rechteckes bestimmen soll.
    • die Klasse enthält eine area-Methode, welche die Fläche des Rechteckes berechnen soll.
    • die Klasse enthält eine toString-Methode, welche als Zeichenkette die Art des Objektes (hier Rectangle), den Ursprung und die Werte für xDelta und yDelta liefert.
Die Klasse Shape.java sieht folgendermaßen aus:
Java:
/** x-coordinate of the origin */
    protected double xOrigin;

    /** y-coordinate of the origin */
    protected double yOrigin;

    /**
     * Constructor for a shape taking as argument the two coordinates of the
     * origin.
     * 
     * @param x
     *            the x-coordinate of the shapes' origin
     * @param y
     *            the y-coordinate of the shapes' origin
     * 
     */
    public Shape(double x, double y) {
        xOrigin = x;
        yOrigin = y;
    }

    /**
     * calculate the area of a shape. the base shape is just point so it has no
     * area.
     * 
     * @return the area of the shape
     */
    public double area() {
        return 0;
    }

    /**
     * calculate the circumference of a shape. the base shape is just point so
     * it has no circumference.
     * 
     * @return the circumference of the shape
     */
    public double circumference() {
        return 0;
    }

    /**
     * constructs a textual representation of the origin in the form: "(x, y)".
     * *
     * 
     * @return the origin on textual representation
     */
    public String origin() {
        return ("(" + xOrigin + ", " + yOrigin + ")");
    }

    /**
     * constructs a textual representation of the object.
     * 
     * @return the current object in a textual representation
     */
    @Override
    public String toString() {
        return ("Shape with origin: " + origin());
    }
}


Nun bekomme ich es leider nicht hin den folgenden ProgrammCode zu schreiben.

Mein Ansatz sieht folgendermaßen aus:
Java:
Public class Rectangle extends Shape


{
    protected double xDelta;
    protected double yDelta;
    protected double Umfang;
    protected double area;

    public Rectangle(double xOrigin,double yOrigin, double xDelta, double yDelta,double Umfang)
    {
    super(xOrigin,yOrigin);

    xDelta=xOrigin/2;
    yDelta=yOrigin/2;
    
    
    }



    public double circumference(xOrigin,yOrigin,Umfang)
    {

    Umfang=(xOrigin+xOrigin+yOrigin+yOrigin);
         return U;
    }

    public double area(xOrigin,yOrigin,area) {
    
    area=(xOrigin*yOrigin);
        return area;
}


Mit dem letzten Punkt kann ich schonmal garnichts anfangen:
-die Klasse enthält eine toString-Methode, welche als Zeichenkette die Art des Objektes (hier Rectangle), den Ursprung und die Werte für xDelta und yDelta liefert.

Was bedeutet Ursprung? Der Ursprung des Koordiantenkreuzes?


Wäre für ein zwei Tipps ziemlich dankbar.


Vielen Dank im Voraus!

Greetz Alex
 
Zuletzt bearbeitet von einem Moderator:
Mein Ansatz sieht folgendermaßen aus:
Zu deinem Code:

* die Klasse soll nur zwei Felder enthalten: xDelta und yDelta, deine Klasse hat zusätzlich Umfang und area
* Dein Konstruktor ignoriert die übergebenen xDelta und yDelta, außerdem ist der Parameter Umfang überflüssig
* circumference und area sollten keine Parameter haben


Was bedeutet Ursprung? Der Ursprung des Koordiantenkreuzes?
Ursprung (englisch "origin") meint xOrigin und yOrigin.
 
Ohwe, du verrennst dich total.

Rectangle erbt von Shape, dass heißt es erbt auch alle Methoden und Attribute von Shape. Die Methoden, welche von der Aufgabenstellung gefordert sind, existieren bereits alle in Shape, d.h. du musst sich überschreiben. Dafür empfehle ich dir eine überschriebene Methode immer mit @Override zu dekorieren, dann sagt dir der Compiler, wenn du etwas falsch gemacht hast.

Umfang und Flaeche sind nicht zu speichern, lass die Attribute raus. Sie sind in area und circumference zu berechnen und zurückzugeben.
 
Java:
    protected double Umfang;
Wo ist das in der Aufgabenstellung gefordert/erlaubt?


Java:
    xDelta=xOrigin/2;
    yDelta=yOrigin/2;
Der Code ist aus mehreren Gründen falsch.
a) was wird da gerechnet? Welchen Sinn hat die Rechnung?
b) du weißt den übergebenen Parametern irgendwelche Werte zu - das bringt nix, du willst vermutlich eher den Felder (also this.xDelta) Werte zuweisen. Und die sind bestimmt nicht xOrigin/2.

Java:
    public double circumference(xOrigin,yOrigin,Umfang)
Warum bekommt die Methode 3 Parameter? Du hast die Werte doch in der Klasse gespeichert. Außerdem soll sie den Umfang berechnen und nicht als Parameter bekommen.

Java:
  public double area(xOrigin,yOrigin,area) {
  
    area=(xOrigin*yOrigin);
        return area;
}
Gleiches wie oben - die Parameter sind Unfug. Und die Rechnung allerdings auch. Es wäre mir zumindest neu, das ich den Umfang eines Rechtecks ermittlte, in dem ich die x- und x- Koordinate einer Ecke miteiander multipliziere.

-die Klasse enthält eine toString-Methode, welche als Zeichenkette die Art des Objektes (hier Rectangle), den Ursprung und die Werte für xDelta und yDelta liefert.

Was bedeutet Ursprung? Der Ursprung des Koordiantenkreuzes?
Ursprung = origi = Deine x/y Werte in originX und originY
 
Ich hab dir mal ein Beispiel gemacht wie das etwa für Kreis aussehen könnte. Schaus dir an, versuch es zu verstehen und dann adaptiere das für dein Rechteck
Java:
public class Circle extends Shape {
    private double radius;

    public Circle(double x, double y, double radius) {
        super(x, y);
        this.radius = radius;
    }

    @Override
    public double area() {
        return Math.PI * radius * radius;
    }

    @Override
    public double circumference() {
        return 2 * Math.PI * radius;
    }

    @Override
    public String toString() {
        return String.format("Circle{radius=%.2f, xOrigin: %.2f, yOrigin: %.2f}", radius, xOrigin, yOrigin);
    }

    public static void main(String... args) {
        Circle circle = new Circle(1, 1, 3);

        System.out.println("Werte für: " + circle); // Java ruft hier die toString Methode auf für circle
        System.out.printf("Umfang: %.2f; Flächeninhalt: %.2f", circle.circumference(), circle.area());
    }
}


Ausgabe:
Code:
Werte für: Circle{radius=3,00, xOrigin: 1,00, yOrigin: 1,00}
Umfang: 18,85; Flächeninhalt: 28,27
 
Zuletzt bearbeitet:
Hey Moxi,

erstmal vielen Dank für die Mühe und dem Beispiel. Die ganze Aufgabe hat sich nun etwas gelichtet.

Mein Code sieht nun folgendermaßen aus:

Java:
[/B]



public class Rectangle extends Shape {
    private double xDelta;
     private double yDelta;



    public Rectangle(double xOrigin, double yOrigin) {
        super(xOrigin, yOrigin);

    }

    @Override
    public double area() {
        return xOrigin*yOrigin;
    }

    @Override
    public double circumference() {
        return 2*xOrigin+2*yOrigin;
    }

    @Override
    public String toString() {
        return String.format("Rectangle{xOrigin: %.2f, yOrigin: %.2f}",xOrigin, yOrigin);
    }

    public static void main(String... args) {
       Rectangle rectangle= new Rectangle(3,4);

        System.out.println("Werte für: " + Rectangle); // Java ruft hier die toString Methode auf für circle
        System.out.printf("Umfang: %.2f; Flächeninhalt: %.2f", Rectangle.circumference(), Rectangle.area());
    }
}
[B]

Habe nur leider das Problem das er das Symbol Rectangle nicht finden kann. Daraus resultieren dann wohl noch 2 weitere Fehler "non-static method circumference() cannot be referenced from a static context"

Was genau habe ich Falsch gemacht? Wieso wird das Symbol Rectangle nicht erstellt?
 
Weil du Rectangle großgeschrieben hast. Der Variablenname ist aber kleingeschrieben. außerdem fehlt dir noch xDelta und yDelta. Zum Verständnis:
Stell dir ein Blatt Papier vor vor. Du platzierst darauf ein Rechteck Schnipsel. Diese Schnipsel hat eine Reißzwecke genau in der Mitte, mit welchem du den Schnipsel auf dem Papier draufpinnst. Die Reißzwecke hat jedes Shape, auch mein Kreis. Die Mitte, wo die Reißzwecke sitzt, wird durch xOrigin und yOrigin implementiert. Das ist lediglich die Position des Schnipsels, nichts Anderes. Dein Rechteck hat aber noch eine Breite und eine Höhe. Die Längen von diesem Mittelpunkt aus (Position) bis zum Rand sind durch xDelta und yDelta zu implementieren. xOrigin und yOrigin haben in deinen Umfang- und Flächeninhalt Methoden nichts zu suchen, schließlich ist es, wie bereits erwähnt, nur die Position.
 
Zuletzt bearbeitet:
Habe mir die Frage selbst beantwortet.. Ohne erstelltest Symbol, kann er nicht damit arbeiten.

Einen Fehler bekomme ich trotzdem noch wenn ich das Symbol vorne im Quelltext erstelle: public vor static void soll ein illegaler Start sein :/
 
Weil du Rectangle großgeschrieben hast. Der Variablenname ist aber kleingeschrieben. außerdem fehlt dir noch xDelta und yDelta. Zum Verständnis:
Stell dir ein UML Diagram Editor vor. Du platzierst darauf ein Rechteck Shape. Die Einfügepunkt ist genau in der Mitte dieses Shapes und wird durch xOrigin und yOrigin implementiert. Das ist lediglich die Position des Shapes, nichts Anderes. Dein Rechteck hat aber noch eine Breite und eine Höhe. Die Längen von diesem Mittelpunkt aus (Position) bis zum Rand sind durch xDelta und yDelta zu implementieren. xOrigin und yOrigin haben in deinen Umfang- und Flächeninhalt Methoden nichts zu suchen, schließlich ist es, wie bereits erwähnt, nur die Position.

Ah, alles klar. Ich gehe das nochmal durch.. Danke dir erstmal!
 
Soooo, bin jetzt nochmal alles durch gegangen und habe noch eine Fehlermeldung übrig, diese lautet:


javac Rectangle.java
Rectangle.java:12: error: illegal start of expression
public Rectangle(double xOrigin, double yOrigin) {
^
1 error

Diese Klasse muss doch aber public sein oder sehe ich da noch was falsch?
 
Bitte bedenke dass ein rechteck 4 Werte hat, Position x, position y, breite, Höhe. Die positionswerte erbt ein Rechteck von Shape. Das sind die werte xOrigin und yOrigin. Aktuell sieht es noch immer so aus als hättest du Breite und Höhe in Form von xDelta und yDelta nicht
 
Mein Quellcode sieht jetzt folgendermaßen aus:

Java:
[/B]
public class Rectangle extends Shape {
    private double xDelta;
     private double yDelta;



    public Rectangle(double xOrigin, double yOrigin, double xDelta,double yDelta) {
        super(xOrigin, yOrigin);

            this.xDelta=xDelta;
            this.yDelta=yDelta;

    }

    @Override
    public double area() {
        return (2*xDelta)*(2*yDelta);
    }

    @Override
    public double circumference() {
        return (2*(2*xDelta))+(2*(2*yDelta));
    }

    @Override
    public String toString() {
        return String.format("rectangle{xOrigin: %.2f, yOrigin: %.2f, xDelta: %.2f, yDelta: %.2f}",xOrigin, yOrigin, xDelta, yDelta );
[B]
 
Wenn ich jetzt eine Subklasse von Rectangle erstellen möchte, nehmen wir mal zum Beispiel ein circle oder ein Square. Würde ich die Klasse eigentlich genau so schreiben. Das Problem was ich nur habe ist, wenn ich jetzt von Rectangle erbe will er auch immer 4 double haben. Beim Square gibt es ja aber nur ein Delta bzw. bei einem circle nur ein Radius.

Wie kann ich diese 4 Fach double Abfrage umgehen?
 
Also circle sollte nie von Rectangle erben, das macht keinen Sinn. Bei Square würdest du einen Konstruktor mit 3 Werten erstellen und den 4 Werte Super Konstruktor aufrufen. Du setzt nur den Seitenlängenwert 2x ein
 
Also circle sollte nie von Rectangle erben, das macht keinen Sinn. Bei Square würdest du einen Konstruktor mit 3 Werten erstellen und den 4 Werte Super Konstruktor aufrufen. Du setzt nur den Seitenlängenwert 2x ein

Ah verstehe, dann sollte square von Rectangle erben und circle dann wieder von Shape.

Denke ich bin jetzt soweit fit das ich das auch noch hin bekomme..


Nochmals vielen vielen Dank! <3
 
Auch wenn es zunächst so scheint, dass ein Square ein Rectangle ist, so stimmt das nicht wirklich!
In einer Klasse Rectangle kann ich eine Methode schreiben, die beispielsweise die Breite verdoppelt ohne die Länge zu verändern. Dies ist in Square jedoch verboten. Also hat ein Square - was das Verhalten betrifft - nicht alle Eigenschaften von Rectangle.
Deshalb sollte auch Square von Shape erben.
 
Darüber lässt sich streiten, Unrecht hast du nicht, rein aus der Geometrie ist die Vererbung schon richtig und eventuell auch das Ziel der Übung. Man könnte ja auch die Breite-verdoppeln Methode wieder überschreiben und einfach nichts tun oder eine Exception werfen oder gleichzeitig die Höhe auch mit verändern.
 
Auch wenn es zunächst so scheint, dass ein Square ein Rectangle ist, so stimmt das nicht wirklich!
In einer Klasse Rectangle kann ich eine Methode schreiben, die beispielsweise die Breite verdoppelt ohne die Länge zu verändern. Dies ist in Square jedoch verboten. Also hat ein Square - was das Verhalten betrifft - nicht alle Eigenschaften von Rectangle.
Deshalb sollte auch Square von Shape erben.

Stimme zwar zT zu, diesen Fall löst man aber einfach, indem man solche Klassen grundsätzlich immutable macht.
 
Die Überlegung, dass ein Quadrat kein Rechteck ist, stammt nicht von mir.
Sie ist schon beschrieben in einem Artikel von Robert C. Martin aus den späten 90-er Jahren des letzen Jahrtausends:
Es geht hierbei um das "Liskov Substitution Principle (LSP)".
Dass es manchmal praktisch sein kann, dieses Prinzip zu verletzen, will ich nicht bestreiten.
 

Zurück
Oben