# Schnittstellen



## JavaIsTheBest (22. Mai 2016)

Hallo,
ich soll bei dieser Aufgabe Java Schnittstellen definieren. Dazu hätte ich ein paar Fragen.

1. Wozu werden die Interfaces Ellipse und Square benötigt?
2. Wäre es falsch, wenn man diese beiden Interfaces weggelassen hätte?


----------



## JStein52 (22. Mai 2016)

Zu 1.) würde ich sagen um den Dingen einen Namen zu geben.
zu 2.) es wäre nicht falsch gewesen aber vielleicht nicht das was der Aufgabensteller sehen wollte 

Edit: siehe ersten Satz der Aufgabenstellung


----------



## JavaIsTheBest (22. Mai 2016)

1. Warum ist die Klasse AbstractFigure abstrakt, obwohl es keine einzige abstrakte Methode gibt? Kann man das "abstract" auch weglassen? Wenn nein, warum nicht?
2. Kann man von einer abstrakten Klasse, einen Konstruktor definieren. Wenn ja, wozu?
3. Warum kann man von abstrakten Klassen Konstruktoren definieren? Man macht doch eine abstrakte Klasse, wenn man kein Objekt dieser Klasse erstellen möchte. 
4. In der Klasse "AbstractIrregularFigure" steht vor dem Konstruktor, der Modifikator protected. Wozu das?(Ich weiß, protected wird verwendet, damit die Unterklasse darauf zugreifen kann)


----------



## InfectedBytes (22. Mai 2016)

1. Da es keine abstrakten Methoden gibt, könntest du das abstract vor der Klasse weglassen, allerdings macht es schon Sinn es stehen zu lassen. Denn dadurch das die Klasse abstrakt ist, kann man kein Objekt daraus erzeugen. Und genau das ist ja das gewünschte Verhalten, denn du willst ja nicht das jemand einfach folgendes macht: AbstractFigure fig = new AbstractFigure();
2. Ja. Eine Unterklasse muss immer einen Konstruktor der Oberklasse aufrufen, implizit wird dabei immer der parameterlose Konstruktor (falls vorhanden) aufgerufen. Wenn du nun also einen Konstruktor in deiner abstrakten Klasse definierst, dann zwingst du die Unterklasse dazu, dass sie diesen Konstruktor aufruft.
3. sieht 2.
4. Im Grunde wieder das Prinzip: Sichtbarkeit so gering wie möglich, aber so groß wie nötig.


----------



## JStein52 (22. Mai 2016)

InfectedBytes hat gesagt.:


> Sichtbarkeit so gering wie möglich, aber so groß wie nötig


Ich glaube mit der 4. Frage war folgendes gemeint: Es können eh keine Objekte der abstrakten Klasse angelegt werden, also wäre die Wirkung die gleiche auch wenn der Konstruktor public wäere ? Er kann eh nur von einem Konstruktor eine konkreten Subklasse aufgerufen werden


----------



## JavaIsTheBest (24. Mai 2016)

InfectedBytes hat gesagt.:


> 2. Ja. Eine Unterklasse muss immer einen Konstruktor der Oberklasse aufrufen, implizit wird dabei immer der parameterlose Konstruktor (falls vorhanden) aufgerufen. Wenn du nun also einen Konstruktor in deiner abstrakten Klasse definierst, dann zwingst du die Unterklasse dazu, dass sie diesen Konstruktor aufruft.



1. Ich verstehe immer noch nicht, warum man einen Konstruktor in einer abstrakten Klasse definiert, wenn man von der Klasse kein Objekt erzeugen will. Das ist doch unnötig?



> Und genau das ist ja das gewünschte Verhalten, denn du willst ja nicht das jemand einfach folgendes macht: AbstractFigure fig = new AbstractFigure();



2. Warum sollte ich das nicht wollen? 
Ich sehe keinen Grund, der dagegen spricht, ein neues Objekt vom Typ Figure zu erstellen, wenn die Klasse nicht abstrakt ist.

3. Und woher weiß ich, dass es sinnvoll ist, wenn die Klassen AbstractRegularFigure, AbstractIrregularFigure, AbstractFigure abstrakt sind?
Was spricht dafür, diese Klassen abstrakt zu machen?


----------



## @SupressWarnings() (24. Mai 2016)

@JavaIsTheBest 
Zu 1: Wenn du zum Beispiel eine Klasse Auto hast, dann möchtest du vielleicht nicht, dass es direkt Autos gibt, aber du möchtest, dass jedes Auto einen Namen, eine Höchstgeschwindigkeit und ein Herstellungsjahr hat. Also schreibst du in der abstrakten Oberklasse diesen festen Konstruktor, der später aufgerufen werden MUSS.

Zu 3: Man kann Klassen abstrakt machen, wenn es nur Unterklassen geben soll. Du könntest natürlich darauf vertrauen, dass der Anwender kein Objekt der Oberklasse erstellt, es ist aber sicherer sie abstrakt zu machen. Die Funktion von Oberklassen ist dann, für viele Unterklassen Variablen und Methoden zu definieren, damit du nicht zehn mal dasselbe in die Klassen schreiben musst.

Ich hoffe das hilft.
@SupressWarnings()


----------



## JavaIsTheBest (24. Mai 2016)

Stimmt, nur die Klassen Kreis, Ellipse, Rechteck und Quadrat sollen laut Aufgabenstellung konkret sein.
Der Rest der klassen sollte abstrakt sein.

Brauche ich den Konstruktor laut Aufgabenstellung in den abstrakten Klassen unbedingt? Steht das irgendwo?
Ich hätte es so gemacht, dass ich nur in den Klassen Kreis, Ellipse, Rechteck und Quadrat Konstruktoren definiert hätte. Wäre das falsch gewesen? Welchen Nachteil hätte ich dabei?


----------



## Joose (24. Mai 2016)

JavaIsTheBest hat gesagt.:


> Ich hätte es so gemacht, dass ich nur in den Klassen Kreis, Ellipse, Rechteck und Quadrat Konstruktoren definiert hätte. Wäre das falsch gewesen? Welchen Nachteil hätte ich dabei?



Solanges es funktioniert und nicht verlangt wurde ist es nicht falsch 

Nachteil: Du musst in jeder deiner Klassen (Kreis, Ellipse, Reckteck und Quadrat) dafür sorgen das die Koordinaten (x und y) gesetzt werden. Vergisst du es kann es zu Problemen kommen. Sprich du hast 4 Klassen wo du 4x die gleichen Anweisungen schreibst (Duplicate Code sollte vermieden werden).
Würdest die abstrakte Basisklasse nun einen Konstruktor mit 2 Parametern (für x und y) bereitstellen, so musst du diesen Konstruktor verpflichtend aufrufen im Konstruktor der Subklassen.


----------



## JavaIsTheBest (24. Mai 2016)

Stimmt, dann hätte ich gleiche Attribute und Methoden mehrfach implelementiert, was unnötig wäre.


----------



## JavaIsTheBest (26. Mai 2016)

1. Warum wird in der Musterlösung dieses "implements XY" in den abstrakten Klassen kommentiert?
Warum wird das an dieser Stelle nicht benötigt?

2. Ich habe das so gemacht, dass in der Klasse AbstractIrregularFigure, der Konstruktor aus der Oberklasse aufgerufen wird. In der Musterlösung wird das nicht so gemacht. Meine Lösung ist trotzdem auch richtig?



Spoiler: Klasse





```
abstract class AbstractIrregularFigure extends AbstractFigure {
    private double breite;
    private double hoehe;
   
    protected AbstractIrregularFigure(double mx, double my, double breite,double hoehe){
        super(mx,my);
        this.breite=breite;
        this.hoehe=hoehe;
    }
    public double getBreite(){
        return breite;
    }
    public double getHoehe(){
        return hoehe;
    }
    public void skaliere(double f){
        breite*=f;
        hoehe*=f;
    }
   
}
```





3. Ich fand das ganze Programm zu programmieren sehr unübersichtlich. Habt ihr Tipps, wie ich den Überblick behalte? So, dass ich nicht vergesse, welche Methoden ich zu implementieren habe?


----------



## mrBrown (26. Mai 2016)

JavaIsTheBest hat gesagt.:


> 1. Warum wird in der Musterlösung dieses "implements XY" in den abstrakten Klassen kommentiert?
> Warum wird das an dieser Stelle nicht benötigt?



Benötigt wird es nicht, man muss dann die Methoden halt doppelt deklarieren.
Ich hätte die Abstrakten Klassen auch das Interface implementieren lassen. 



JavaIsTheBest hat gesagt.:


> 2. Ich habe das so gemacht, dass in der Klasse AbstractIrregularFigure, der Konstruktor aus der Oberklasse aufgerufen wird. In der Musterlösung wird das nicht so gemacht. Meine Lösung ist trotzdem auch richtig?



Man sollte immer den Oberkonstruktor aufrufen, wenn das aber nur der Defaultkonstruktor, wird der implizite aufgerufen, in der Musterlösung braucht man das also nicht. Schöner ist's allerdings, einen Konstruktor zu haben, der die privaten Werte setzt, in der MusterLösung müsste man erst #move aufrufen.



JavaIsTheBest hat gesagt.:


> 3. Ich fand das ganze Programm zu programmieren sehr unübersichtlich. Habt ihr Tipps, wie ich den Überblick behalte? So, dass ich nicht vergesse, welche Methoden ich zu implementieren habe?



Naja, die Interfaces geben dir vor, welche Methoden implementiert sein. Also als erstes die nötigen Interfaces angeben, dann implementieren. Sollte was fehlen, sagt dir spätestens der Compiler bescheid.
Ansonsten, vorher vernünftig planen, zb UML-Diagramme erstellen


----------



## JavaIsTheBest (26. Mai 2016)

Zu 1)
Kannst du mir ein Beispiel nennen, welche Methode dann doppelt implementiert werden muss?

Zu 2) Also wäre meine Lösung auch richtig?


----------



## JavaIsTheBest (26. Mai 2016)

Und in der Klasse AbstractFigure werden nicht alle Methoden, der Schnittstelle Figure implementiert. Z.B ist die Methode scale/skaliere in der abstrakten Klasse nicht dabei.
Woher weiss ich, welche Methoden ich in dieser Klasse benötige und welche nicht?


----------



## mrBrown (26. Mai 2016)

JavaIsTheBest hat gesagt.:


> Zu 1)
> Kannst du mir ein Beispiel nennen, welche Methode dann doppelt implementiert werden muss?



implementiert wird jede nur einmal, nur deklariert werden sie doppelt.



JavaIsTheBest hat gesagt.:


> Zu 1)
> Zu 2) Also wäre meine Lösung auch richtig?



Ja



JavaIsTheBest hat gesagt.:


> Und in der Klasse AbstractFigure werden nicht alle Methoden, der Schnittstelle Figure implementiert. Z.B ist die Methode scale/skaliere in der abstrakten Klasse nicht dabei.
> Woher weiss ich, welche Methoden ich in dieser Klasse benötige und welche nicht?



AbstractFigure implementiert Figure auch nicht zumindest nicht in der Musterlösung.
In abstracten Klassen immer das implementieren, was für alle möglichen Unterklassen gleich wäre


----------



## JavaIsTheBest (26. Mai 2016)

mrBrown hat gesagt.:


> implementiert wird jede nur einmal, nur deklariert werden sie doppelt.



Du meinst, dass die abstrakten Methoden, dann mehrfach dastehen?


----------



## mrBrown (26. Mai 2016)

Jein, wenn man es so macht, wie in der Musterlösung, dann muss man die Deklaration aus dem Interface in die Abstrakte Klasse kopieren, und erst in der Klasse, die dann das Interface implementiert, merkt man zB Tippfehler (das Interface muss nicht mal implementiert werden, dann gäbe es abstrakte Figuren, die keine Figuren gibt).

Implementiert man das Interface stattdessen schon in der abstrakten Klasse, muss da zwingend die korrekte Methode implementiert werden (wenn man @Override benutzt). Außerdem ist dann auch zwingen jeder abstrakte Figur eine Figur.


----------



## JavaIsTheBest (26. Mai 2016)

Wenn ich die Fläche eines Kreises berechnen will, dann erhalte ich immer den Wert 0.
Das liegt am Konstruktor.
Wäre es schlechter Programmierstil, wenn ich zuerst super(0,0,r); aufrufe und dann erst this.radius=r; zuweise?
Weil, so würde es funktionieren.



Spoiler: AbstractRegularFigure





```
abstract class AbstractRegularFigure extends AbstractFigure{
    private double groesse;
   
    protected AbstractRegularFigure(double mx, double my, double groesse){
        super(mx,my);
        this.groesse=groesse;
    }
    public double size(){
        return groesse;
    }
    public double getBreite(){
        return groesse;
    }
    public double getHoehe(){
        return groesse;
    }
    public void skaliere(double f){
        groesse*=f;
    }

}
```






Spoiler: KreisImpl





```
public class KreisImpl extends AbstractRegularFigure implements Kreis{
    private double radius;
    public KreisImpl(double r){
        super(0,0,r);
    }
    public double radius(){
        return radius;
    }
    public double getFlaeche(){
        double f=Math.PI*radius*radius;
        return f;
    }

}
```






Spoiler: Main





```
public class FigureTest {

    public static void main(String[] args) {
        KreisImpl k=new KreisImpl(3);
       
        System.out.println(k.getBreite());
        System.out.println(k.getFlaeche());
        k.skaliere(2);
        System.out.println(k.getBreite());
        System.out.println(k.getHoehe());

    }

}
```


----------



## mrBrown (26. Mai 2016)

JavaIsTheBest hat gesagt.:


> Wenn ich die Fläche eines Kreises berechnen will, dann erhalte ich immer den Wert 0.
> Das liegt am Konstruktor.
> Wäre es schlechter Programmierstil, wenn ich zuerst super(0,0,r); aufrufe und dann erst this.radius=r; zuweise?
> Weil, so würde es funktionieren.



Du musst immer erst super(...) aufrufen, bevor du irgendwas anderes machen kannst, also der richtige Weg. Macht es denn sinn, Radius und Größe zu speichern, wenn beides das gleiche ausdrückt?


----------



## JavaIsTheBest (26. Mai 2016)

mrBrown hat gesagt.:


> Macht es denn sinn, Radius und Größe zu speichern, wenn beides das gleiche ausdrückt?



Nein, macht es nicht. 


Was mir noch auffällt. Der Konstruktor wird in der Klasse AbstractFigure (Musterlösung) ohne die Mittelspunktskoordinaten erstellt. Obwohl das doch laut Aufgabenstellung so sein soll?

Meine Lösung:



Spoiler: AbstractFigure





```
abstract class AbstractFigure {
    private double mx;
    private double my;
   
    protected AbstractFigure(double mx, double my){
        this.mx=mx;
        this.my=my;
    }
    public double getX(){
        return mx;
    }
    public double getY(){
        return my;
    }
    public void move(double x, double y){
        this.mx+=x;
        this.my+=my;
    }

}
```


----------



## mrBrown (26. Mai 2016)

Das auch AbstractFigure die Mittelpunktskoordinaten übergeben werden müssen, steht da so mEn nicht, implizite werden sie auf 0 gesetzt, und lassen sich ja dann mit #move verändern


----------



## JavaIsTheBest (26. Mai 2016)

> Die Mittelpunktskoordinaten werden immer mit 0 initialisiert.



Das geschieht schon automatisch in den privaten Objektvariablen, dass diese mit 0 initialisiert werden?


----------



## mrBrown (26. Mai 2016)

primitive Typen sind immer mit 0 (bzw false) vorbelegt.
Der Abschnitt liest sich aber jetzt doch so, das der Konstruktor keine Position annehmen soll, sondern diese immer auf 0,0 gesetzt werden soll.


----------



## JavaIsTheBest (26. Mai 2016)

Danke für deine Hilfe.


----------

