Flächeninhalt Programmaufgabe

GuStaV%%

Mitglied
Hallo zusammen,

ich hatte eine Studienaufgabe und wollte gerne mal hören, was ihr zu meinen Lösungen sagt:

Aufgabe:

Zweidimensionale geometrische Figuren können über unterschiedliche Charakterisitka definiert werden. Gemeinsam ist ihnen, dass der Flächeninhalt eine interessante Kenngröße ist.
Diesem Umstand kann Rechnung getragen werden, indem eine Schnittstelle GeometricShape
angeboten wird, die eine Methode area enthält, die den Flächeninhalt als double-Wert
zurückgibt.

a) Geben Sie eine Implementation der Schnittstelle GeometricShape an.

Meine Lösung:

interface GeometricShape {
double area( ) {
}
}

b) Basierend auf einer solchen Schnittstelle könnte nun eine Klasse Circle definiert werden,
die zusätzlich ein double-Attribut radius besitzt. Geben Sie eine Implementation der Klasse Circle an.

Meine Lösung:

public class Circle implements GeometricShape {
private double radius;

public Circle ( double radius) {
this.radius = radius;
}

public double area ( ) {
double ergebnis = 2* this.radius * Maht.PI;
return ergebnis;
}

}

c) Wir nehmen nun weiterhin an, dass eine Klasse Rectangle gegeben sei, die die
privaten Attribute a und b mit Getter und Setter getA, getB, setA, setB besitzt, um die Höhe und die Breite des Rechtecks zu repräsentieren. Ein spezielles Rechteck stellt das Quadrat dar, bei dem Höhe und Breite gleich sind. Geben Sie, basierend auf der Klasse Rectangle,
eine Implementation der Klasse Square an, die der Spezialisierungseigenschaft Rechnung
trägt. Stellen Sie dabei insbesondere sicher, dass ein Quadrat auch wirklich nur mit
gleichen Höhen und Breiten existieren kann.

Meine Lösung:

public class Square extends Rectangle {

public Square (double a, double b) {
if (a != b ) {
throw new IllegalArgumentExcetion();
}
this.a = a;
this.b = b;
}

public double area (double a, double b) {
double ergebnis = a * b;
return ergebnis;
}
}

d) Wir wollen nun die Rectangle-Klasse um eine Methode scale erweitern, die eine
positive double-Zahl factor entgegen nimmt und das Rechteck derart skaliert, dass die Fläche um den Faktor factor skaliert wird. Die Fläche des Rechtecks soll also nach Anwendung der Methode ein factor-faches der ursprünglichen Fläche sein, ohne das Verhältnis der Seitenlängen zu ändern. Falls eine unzulässige (also nicht-positive) Skalierung
angefordert wird, soll eine Ausnahme geworfen werden.

Meine Lösung:

public class Rectangle.....


public double scale ( double zahl) {

double x = this.a * zahl;
double y = this.b * zahl;
double ergebnis = area ( x, y);
return ergebnis;
}

e) Erstellen Sie eine ArrayList mit einem Square-Objekt und einem Circle-Objekt und geben
Sie mit Hilfe einer Schleife deren Flächen aus.

Meine Lösung:

List<ArrayList> liste1 = new ArrayList<GeometricShape>();

liste1.add(new Square(3, 3));
liste1.add(new Circle(5));

for (int i = 0; i <liste1.size(); i++ ) {
System.out.println(liste1.area());
}

Seid bitte nicht zu hart zu mir, ich bin noch Anfänger : ).

Was sagt ihr zu meinem Code und meinen Lösungen? Sind Fehler drin und wenn ja, wo und warum ?

Vielen Dank im Voraus.
 

GuStaV%%

Mitglied
hmmm okay, werde ich in Zukunft machen.

Okay, bei dem Teil habe ich mich wohl verschrieben.

Ich hätte gerne gehört, ob es Programmiertechnisch richtig ist.

Gerade z.B. das Interface habe ich ja ohne Parameter deklariert, aber implementieren tue ich es einmal mit 1 Parameter und in der anderen Klasse mit 2 Parameter. Passt das?

Und sonst allgemein? Grobe Fehler drin?
 

thecain

Top Contributor
Ein Interface hat keine Implementierung in deinem Fall, das ist sicher schonmal falsch. Tipp den Code doch mal ab. Du wirst so schon viele Fehler finden
 

temi

Top Contributor
Ein Interface hat doch nie eine Implementierung.... ?! Das passt schon, oder was meinst du?
Eben! Es darf auch keine haben und die geschweiften Klammern stellen sozusagen eine "leere" Implementierung dar.

Tipp: Gewöhne dir gleich an, immer @Override zu verwenden, wenn du eine Methode überschreiben möchtest. Damit kann dich der Compiler sofort darauf aufmerksam machen, wenn du versehentlich überlädst anstatt zu überschreiben:
Java:
@Override
public double area ( ) {
    double ergebnis = 2* this.radius * Maht.PI;
    return ergebnis;
}

Die Klasse Quadrat ist fehlerhaft. Lies dir die Aufgabe nochmal durch und denke über Zugriffsmodifikatoren nach!
 
Zuletzt bearbeitet:

fhoffmann

Top Contributor
- Du berechnest die Fläche des Kreises falsch.
- In der Methode scale von Rechteck, sollst du das Rechteck verändern (du berechnest nur die Fläche des geänserten Rechtecks) und die Fläche soll sich um faktor vergrößern (bei dir vergrößert sie sich um faktor*faktor).
- Die Deklaration List<ArrayList> liste1 = new ArrayList<GeometricShape>(); ist falsch.
 

GuStaV%%

Mitglied
Okay, ich habe meinen Code noch mal um einiges umgestellt und jetzt passt es mal soweit :).

Das wäre die Klasse Quadrat jetzt:

Java:
public class Square extends Rectangle {
    
    
    public Square( double a, double b) {
        
        if ( a!= b) {
            throw new IllegalArgumentException();
            
        }
        
        this.a = a;
        this.b = b;

    }
    
    public double area() {
        
        double ergebnis = a * b;
        return ergebnis;
    }
    
    
}



und das ein Test:

Java:
public class Test {
    
    public static void main(String[] args) {
        
        GeometricShape[] liste1 = new GeometricShape[2];

        liste1[0] = new Square(3, 3);
        liste1[1] = new Circle(5);

        for (int i = 0; i <liste1.length; i++ ) {
        System.out.println(liste1[i].area());
        }
        
    }

}


Ich habe das mit ArrayList weggelassen, weil es bei mir einfach nicht klappen wollte, warum auch immer.

Die Fläche des Kreises habe ich jetzt geändert auf : double ergebnis = (this.radius*this.radius) * Math.PI;

Sollte so passen, oder?


Mal noch eine Frage:

Wenn ich eine Klasse wie Square von Rectangle erben lasse, dann erbt diese ja auch die Attribute und Konstruktoren. Wenn ich im Konstruktor von Square den Superklassenkonstruktor aufrufen möchte, mit super (a, b), dann müssen diese Attribute in Rectangle immer als protected deklariert sein, oder?

Wenn ich sie als private deklariere, dann kann ich sie leider nicht initialisieren, heißt das, dass ich in einem solchen Fall die Attribute der Superklasse immer als protected deklarieren sollte, oder wie macht ihr das?

VIelen Dank
 
K

kneitzel

Gast
Wenn ich eine Klasse wie Square von Rectangle erben lasse, dann erbt diese ja auch die Attribute und Konstruktoren. Wenn ich im Konstruktor von Square den Superklassenkonstruktor aufrufen möchte, mit super (a, b), dann müssen diese Attribute in Rectangle immer als protected deklariert sein, oder?

Wenn ich sie als private deklariere, dann kann ich sie leider nicht initialisieren, heißt das, dass ich in einem solchen Fall die Attribute der Superklasse immer als protected deklarieren sollte, oder wie macht ihr das?
Der Konstruktor initialisiert diese doch. Daher können sie auch private sein und Dein Konstruktor von Square ruft den Konstruktor mit super(a,b) auf.

Und protected hat den Nachteil, dass du keine so gute Kapselung hast. Das kann man machen, aber da würde ich eher Getter hinzufügen um an die Werte zu kommen. (Du willst ja scheinbar immutable Instanzen haben, weshalb das vergrößern nicht die Instanz selbst geändert hat sondern eine neue Instanz zurück gegeben hat. Daher würde ich dies nicht aufweichen!
 

mihe7

Top Contributor
Wenn ich eine Klasse wie Square von Rectangle erben lasse, dann erbt diese ja auch die Attribute und Konstruktoren. Wenn ich im Konstruktor von Square den Superklassenkonstruktor aufrufen möchte, mit super (a, b), dann müssen diese Attribute in Rectangle immer als protected deklariert sein, oder?
Nein, warum?
Java:
public class Rectangle {
    private final int width, height;
    public Rectangle(int w, int h) {
        width = w;
        height = h;
    }
    public double area() { return width * height; }
}

Java:
public class Square extends Rectangle {
    public Square(int size) {
        super(size, size);
    }
}

Warnung: Quadrat von Rechteck abzuleiten, ist gefährlich. Das funktioniert hier zwar, aber im Allgemeinen ist hier Vorsicht geboten, um nicht gegen das Liskovsche Substitutionsprinzip zu verstoßen. Spätestens, wenn Breite und/oder Höhe des Rechtecks veränderbar sind, ist die Ableitung falsch.
 

GuStaV%%

Mitglied
Okay, ich habe jetzt mal etwas ausprobiert:

Java:
public class Rectangle implements Geo{

    private double a;
    private double b;
    
    public Rectangle( double a,  double b) {
        
        this.a = a;
        this.b = b;
    
    }
    
    public double area () {
        
        double ergebnis = this.a * this.b;
        return ergebnis;
    }
    
    
}


[CODE lang="java" highlight="12"]public class Square extends Rectangle {


public Square( double a, double b) {

super (a, b);

}

public double area() {

double ergebnis = a * b;
return ergebnis;
}


}[/CODE]

Hier bekomme ich in der Methode area() in Square immer die Fehlermeldung dass b als protected deklariert werden müsse....
 

Meniskusschaden

Top Contributor
Wenn ich eine Klasse wie Square von Rectangle erben lasse, dann erbt diese ja auch die Attribute und Konstruktoren.
Die Attribute (und die Methoden) werden vererbt, die Konstruktoren nicht. Deine Square-Klasse hat keinen sinnvollen Konstruktor und erlaubt zudem die Erzeugung nicht quadratischer "Quadrate". Im Beitrag von @mihe7 ist es viel besser gelöst.
Außerdem beachtest du noch nicht, dass Rectangle laut Aufgabenstellung setter-Methoden hat.
 

BlackBookOne

Mitglied
Also bezüglich des Quadrats hätte ich das so gemacht:
Java:
package geo;

public class Rect implements GeometricShape {
    public static void main(String[] args) {
        GeometricShape mySquare = new Square(5, 5);
        System.out.println(mySquare);
        System.out.println(mySquare.area());
        ((Square) mySquare).scale(2.0);
        System.out.println(mySquare);
        System.out.println(mySquare.area());
    }

    private double a, b;

    public Rect(double a, double b) {
        this.a = a;
        this.b = b;
    }

    @Override
    public double area() {
        return a * b;
    }

    /**
     * @return the a side
     */
    public double getA() {
        return a;
    }

    /**
     * @return the b side
     */
    public double getB() {
        return b;
    }

    /**
     * @param a the a side to set
     */
    public void setA(Object caller, double a) {
        if (!(caller instanceof Square)) {
            throw new IllegalAccessError("Only Rectangle or Square is allowed to change itself.");
        }
        this.a = a;
    }

    /**
     * @param b the b side to set
     */
    public void setB(Object caller, double b) {
        if (!(caller instanceof Square)) {
            throw new IllegalAccessError("Only Rectangle or Square is allowed to change itself.");
        }
        this.b = b;
    }

    @Override
    public String toString() {
        return String.format("Rect [a=%s, b=%s]", a, b);
    }
}

class Square extends Rect {
    public Square(double a, double b) {
        super(a, b);
        if (a != b) {
            throw new IllegalArgumentException();
        }
    }

    public void scale(double f) {
        if (f <= 0) {
            throw new IllegalArgumentException();
        }
        f = Math.sqrt(f);
        setA(this, getA() * f);
        setB(this, getB() * f);
    }
}

interface GeometricShape {
    public double area();
}
 

fhoffmann

Top Contributor
Im Konstuktor von Square braucht man keine Exception zu werfen; man kann einfach schreiben:
Java:
class Square extends Rect {
    public Square(double x) {
        super(x, x);
    }
    // ...
}

Edit: Stattdessen sollte man die set-Methoden überschreiben und dort eine Exception werfen.
 

BlackBookOne

Mitglied
Danke.
Wäre es denn so besser?
Code:
package geo;

public class Rect implements GeometricShape {
    public static void main(String[] args) {
        GeometricShape mySquare = new Square(5);
        System.out.println(mySquare);
        System.out.println(mySquare.area());
        ((Square) mySquare).scale(2.0);
        System.out.println(mySquare);
        System.out.println(mySquare.area());
    }

    private double a, b;

    public Rect(double a, double b) {
        if (a <= 0 || b <= 0) {
            throw new IllegalArgumentException("Impossible Rectangle.");
        }
        this.a = a;
        this.b = b;
    }

    @Override
    public double area() {
        return a * b;
    }

    /**
     * @return the a side
     */
    public double getA() {
        return a;
    }

    /**
     * @return the b side
     */
    public double getB() {
        return b;
    }

    /**
     * @param a the a side to set
     */
    public void setA(double a) {
        if (a <= 0) {
            throw new IllegalArgumentException("Impossible side length.");
        }
        this.a = a;
    }

    /**
     * @param b the b side to set
     */
    public void setB(double b) {
        if (b <= 0) {
            throw new IllegalArgumentException("Impossible side length.");
        }
        this.b = b;
    }

    @Override
    public String toString() {
        return String.format("Rect [a=%s, b=%s]", a, b);
    }
}

class Square extends Rect {
    public Square(double a) {
        super(a, a);
    }

    public void scale(double f) {
        if (f <= 0) {
            throw new IllegalArgumentException("Impossible dimensions.");
        }
        f = Math.sqrt(f);
        if (f == 0) {
            throw new IllegalArgumentException("Impossible dimensions.");
        }
        setA(getA() * f);
    }

    /**
     * @param a the a side to set
     */
    public void setA(double a) {
        super.setA(a);
        super.setB(a);
    }

    /**
     * @param b the b side to set
     */
    public void setB(double b) {
        super.setA(b);
        super.setB(b);
    }
}

interface GeometricShape {
    public double area();
}
 

temi

Top Contributor
Hier bekomme ich in der Methode area() in Square immer die Fehlermeldung dass b als protected deklariert werden müsse....
Du könntest auch einfach die getter verwenden, um an die entsprechenden Werte zu kommen. Die sind ja genau deswegen auch "public". Aber da die Berechnung der Elternklasse ja völlig identisch ist, gibt es eh keinen Grund die zu überschreiben.
 

Ähnliche Java Themen

Neue Themen


Oben