Interface & Comparable

lubi27X

Aktives Mitglied
Hallo zusammen, bräuchte mal wieder etwas Hilfe bei einer Aufgabe.
Ich habe eine abstrakte Klasse "Figur" und zwei Subklassen "Rechteck" und "Kreis", welche von Figur erben. Nun soll ich einen in der Klasse Figur eine Schnittstelle "Comparable" implementieren, so dass sich die Objekte nach Größe der Fläche sortieren lassen.
Die Oberklasse und Unterklasse habe ich soweit, doch meine Sortierung sieh irgendwie hässlich aus..
In Zeile 18 und 19 meiner main-Methode wird mir nur eine 1 oder -1 ausgespuckt. Ich würde gerne eine ordentliche Sortierung haben...
Java:
public abstract class Figur{
    //Abstrakte Methoden
        public abstract void zeichne();
        public abstract double getFlaeche();
}
Java:
public class Kreis extends Figur implements Comparable<Figur> {
    
    //Attribut
    double radius;
    
    //Konstruktor
    Kreis(double radius) {
        this.radius = radius;
    }
    
    @Override
    public void zeichne() {
        System.out.println("Der Radius beträgt " + this.radius + " und die Fläche beträgt " + this.getFlaeche());
    }

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

    @Override
    public int compareTo(Figur other) {
//        if (this.getFlaeche() > other.getFlaeche())
//        {
//            return (int) this.getFlaeche();
//        }
//        return (int) other.getFlaeche();
        
        return Double.compare(this.getFlaeche(), other.getFlaeche());
    }
}
Java:
public class Rechteck extends Figur implements Comparable<Figur>{
    
    double breite;
    double hoehe;
    
    Rechteck(double b, double h) {
        this.breite = b;
        this.hoehe = h;
    }
    
    @Override
    public void zeichne() {
        System.out.println("Die Breite beträgt: " + this.breite + " die Höhe beträgt: " + this.hoehe + " und die Fläche beträgt: " + this.getFlaeche());
    }

    @Override
    public double getFlaeche() {
        return this.breite * this.hoehe;
    }

    @Override
    public int compareTo(Figur other) {
//        if (this.getFlaeche() > other.getFlaeche())
//        {
//            return (int) this.getFlaeche();
//        }
//        return (int) other.getFlaeche();
        return Double.compare(this.getFlaeche(), other.getFlaeche());
    }
}
Java:
import java.util.Arrays;

public class main {

    public static void main(String[] args) {
        Kreis k1 = new Kreis(5.2);
        Kreis k2 = new Kreis(8.9);
        Rechteck r1 = new Rechteck(14,19);
        Rechteck r2 = new Rechteck(45,99);
        Rechteck r3 = new Rechteck(120,500);
        
        System.out.println("Die Fläche von k1 beträgt: " + k1.getFlaeche());
        k1.zeichne();
        
        System.out.println("Die Fläche von r1 beträgt: " + r1.getFlaeche());
        r1.zeichne();
        
        System.out.println(r1.compareTo(k1));
        System.out.println(k2.compareTo(r2));
        
//        Rechteck[] rck = {r1,r2,r3};
//       
//        Arrays.sort(rck);
//        System.out.println(rck);
    }
}
 
In Zeile 18 und 19 meiner main-Methode wird mir nur eine 1 oder -1 ausgespuckt. Ich würde gerne eine ordentliche Sortierung haben...
Eine wirkliche Sortierung musst du dann selber schreiben oder eine fertige Sortierfunktion benutzen.
Wichtig beim Sortieren ist nur, dass das Programm weiß, welches von zwei Elementen größer als das andere ist. Und dafür hast du das Interface "Comparable" implementiert, das genau diese Frage beantwortet.
 
Das bedeutet, dass ich die Arrays.sort() in meinem Fall nicht einfach benutzen kann, sondern die Methode nochmal neu in meinen Klassen Rechteck und Kreis schreiben muss?
 
Nein, du musst das nicht neu schreiben. Aber das Comparable Interface dient ja nur dazu, um zu sagen: erstes Element ist kleine, gleich oder größer (Im Sinne der Sortierung). Also negativer Wert, 0, positiver Wert als Rückgabe.

Und wenn Du Dir die Klasse Arrays anschaust, speziell die Sort Methode, dann findest Du da:
public static void sort(Object[] a)
Sorts the specified array of objects into ascending order, according to the natural ordering of its elements. All elements in the array must implement the Comparable interface.

Also mit der Implementation von Comparable bist Du jetzt in der Lage, ein Array von Instanzen dieser Klasse mit Arrays.sort zu sortieren.
 
Jo, habe es jetzt verstanden, danke... Sort() sortiert mir hier alle Objekte aufsteigend anhand der Fläche(So verstehe ich das).

Jetzt kann ich die Werte mit einer for-Schleife ausgeben lassen.

Lediglichdie einzelnen Objekte ausgeben lassen bekomme ich nicht hin.
Ich will, dass da in Zeile 8, bei "Arrays.toString(liste), k1, k2 etc. steht.
Java:
        Figur[] liste = {k1,k2,r1,r2,r3};
        Arrays.sort(liste);
       
        System.out.println(Arrays.toString(liste[2]));
       
        for (int i = 0; i < liste.length; ++i)
        {
            System.out.println("Platz "+ (i + 1) + " ist " + Arrays.toString(liste[i])+ " mit einer Fläche von " + liste[i].getFlaeche());
        }
       
    }
}
 
Zuletzt bearbeitet:
k1, k2 sind ja nur Variablennamen. Die hast Du in dem Array ja nicht mehr.
Du kannst also maximal den Inhalt ausgeben, den Du in der Instanz hast Dazu könntest Du die toString Methode überschreiben.
 
ah okay..Das bedeutet, dass ich an die Variablennamen jetzt gar nicht mehr ran komme? Wäre halt schön, wenn der variablenname da noch steht und mann weiß um welches Objekt es sich handelt.
 
Du hast die Variable doch gar nicht mehr. Du hast ein Array aus Referenzen. Die Variablen könnten sonst was für neue Werte bekommen:
Java:
Figur[] liste = {k1,k2,r1,r2,r3};
k1 = null;

Die Instanz aus k1 ist in der liste, aber k1 selbst ist null....
Oder was ist wenn Du ein Array aus 5 Elementen hast und dann die Variable k1 nutzt um die ersten zwei Elemente zu setzen ...

Oder Du hast eine Instanz aber k1, k2, k3, k4, k5 enthalten alle eine Referenz auf die Instanz?

Also bitte wirklich differenzieren zwischen Variablen und dem Inhalt. Bei der Anzeige wird einfach nur der Inhalt ausgegeben. Der hat kein Wissen, welche Variablen evtl. darauf verweisen.

Wenn Du so Daten als wichtig empfindest, dann musst Du es entsprechend modellieren. Dann hat die Klasse noch eine Instanzvariable name oder so und dann kannst Du diese ausgeben.
Oder wenn Du einen Zusammenhang von Name auf so eine Instanz brauchst, dann hast Du von mir aus eine Map.
 
Vielleicht ist die alte C-Ausdrucksweise mit Zeigern für einen Anfänger etwas leichter verständlich.
Der Kreis selbst (die Instanz) liegt irgendwo im Speicher, die Variable k1 ZEIGT darauf (ist also in Java eine Referenz).
Jedes Feld im Array zeigt ebenfalls auf Kreise.
1. Wenn du die Werte des Arrays änderst (wodurch auch immer), bleiben alle Kreise im Speicher, wo sie sind, nur die Zeiger/Referenzen in den Feldern ändern sich.
2. Wenn du k1 in das Array kopierst, dann wird der Zeiger auf den Kreis reinKOPIERT, k1 und das Array bleiben unabhängig voneinander, d.h.
2.1 fallst du danach k1 änderst, bleibt das Array gleich.
2.2 falls du das Array umsortierst, bleibt k1 gleich.
 
Eine wirkliche Sortierung musst du dann selber schreiben oder eine fertige Sortierfunktion benutzen.
Wichtig beim Sortieren ist nur, dass das Programm weiß, welches von zwei Elementen größer als das andere ist. Und dafür hast du das Interface "Comparable" implementiert, das genau diese Frage beantwortet.
Der Fehler mit dem Sortieren passiert mir auch öfter. Aber wenn man einmal weiß, worauf man achten muss, klappt das mit dem Interface besser! Ist reine Übungssache 💪
 
Ich habe jetzt in meiner Klasse Kreis und Rechteck das Attribut "name" hinzugefügt und jeder Instanz einen namen "verpasst". Über die for-Schleife gebe ich den Namen zusätzlich aus..
Hat doch noch mit einem einfachen Bauerntrick funktioniert...
 
Vielleicht ist die alte C-Ausdrucksweise mit Zeigern für einen Anfänger etwas leichter verständlich.
Der Kreis selbst (die Instanz) liegt irgendwo im Speicher, die Variable k1 ZEIGT darauf (ist also in Java eine Referenz).
Jedes Feld im Array zeigt ebenfalls auf Kreise.
1. Wenn du die Werte des Arrays änderst (wodurch auch immer), bleiben alle Kreise im Speicher, wo sie sind, nur die Zeiger/Referenzen in den Feldern ändern sich.
2. Wenn du k1 in das Array kopierst, dann wird der Zeiger auf den Kreis reinKOPIERT, k1 und das Array bleiben unabhängig voneinander, d.h.
2.1 fallst du danach k1 änderst, bleibt das Array gleich.
2.2 falls du das Array umsortierst, bleibt k1 gleich.
Das ist eine super Veranschaulichung....

Wenn ich das richtig verstehe, ändert man nie den Inhalt des Arrays, sondern die Referenzen auf den Inhalt des Arrays.
 
Referenzen auf den Inhalt des Arrays? Der Inhalt des Arrays sind Referenzen auf Figuren.
Was du sortierst, sind die Referenzen, die Figuren selbst bleiben im Speicher genau da, wo sie sind.

Nach der Zuweisung liste[0] = k1 zeigen liste[0] und k1 auf die selbe Figur.
k1 = neueFigur1;
liste[0] = k1; //bzw Initialisierung des Arrays mit k1 an der ersten Stelle
sortiere(liste);
Die Referenz aus liste[0] ist durch das Sortieren z.B. nach Position 3 gewandert, jetzt gilt Jetzt gilt k1 == liste[3]

Umgekehrt kannst du z.B. das hier machen.
k1 = neueFigur1;
liste[0] = k1; //bzw Initialisierung des Arrays mit k1 an der ersten Stelle
k1 = neueFigur2;
Es gibt nun im Array überhaupt keine Referenz auf neueFigur2.
 

Zurück
Oben