Interface, this etc.

Googlehupf

Erfahrenes Mitglied
Hallo zusammen!

Ja, ich hab gegoogelt und hab folgende Beschreibung gefunden:
http://www.java-forum.org/einfuehrungen-erste-schritte/117297-interfaces.html

Das Programm ohne Interface ist mir vollkommen klar, aber das mit dem Interface verwirrt mich ein wenig(Fragen sind in den Kommentaren der Programme).

Das Interface-Programm ist ja folgendermaßen aufgebaut:
Java:
interface Buyable() {
    public int getPrice();
}
 
class Car implements Buyable{
 
    @Override
    public int getPrice() {
        return 15000;
    }
}
 
class Truck implements Buyable{
 
    @Override
    public int getPrice() {
        return 45000;
    }
}
 
class Motorbike implements Buyable{
 
    @Override
    public int getPrice() {
        return 8000;
    }
}
 
class CarDealer {
 
    private int billingAmount;
 
    public void buyBuyable(Buyable b) { //an der stelle: "Buyable b" ="new Car()", also die Adressen sind von beiden dieselbe, oder? Wenn nicht wie nennt man das sonst? Ich begreif jetzt nicht wie jetzt "b.getPrice" die Auto-Klasse finden soll und halt dann darin die Funktion getPrice aufruft.
        billingAmount += b.getPrice();
    }
    
    public void printBill() {
        System.out.println("Der Betrag Ihres Einkaufs beläuft sich auf:");
        System.out.println(billingAmount + " €.");
        System.out.println("Danke für Ihren Einkauf bei MegaMüll Vehicles.");
    }
}

Warum muss man denn "Buyable b"(das interface) mit "new Car" gleichstellen? Also übergeben(=gleichstellen). Also was passiert da genau?


Anders Programm mit Interface:
Java:
//Klasse1 die das interface implementiert hat:
bar = new Label_Scrollbar(easy,this);// hier meint man ja man übergibt die Adresse des Objektes von Klasse1, oder was hat macht das genau?

//Klasse 2:
public Label_Scrollbar(int level, LevelChangeObserver cb) { //man übergibt Klasse1, das ja ein Interface implementiert, weil man //in der Klasse 1 später irgendwann mal auf die Methode vom Interface zugreifen kann, aber was für Vorteile hat das hier jetzt in //dem Programm? Erklärt mir bitte die Zeile in KLasse 1 mit der Konstruktor-Zeile in Klasse 2 --> was passiert da genau?
		super(JScrollBar.VERTICAL, 1, 1, 0, 3);
		this.cb=cb;
		this.level=level;
		addAdjustmentListener(new Scrollbar_Listener());//frage nebenbei: theoretisch könnte man hier auch ein this. machen //oder? Man brauchst aber nicht, weils eh eindeutig ist, dass die Klasse "Label_Scrollbar" gemeint wird, richtig?
		color_Change();	
}

Interface:
public interface LevelChangeObserver {
	public void change_level(int value);
}

Interface-Methode, die natürlich in der Klasse 1 steht:
public void change_level(int new_level) {
		level = new_level;
}


Ich denke was das Programm genau machen soll ist eigentlich egal, ansonsten bitte nachfragen.

Bitte versucht es bei beiden Programmen mir zu erklären, wenn ihr wollt könnt ihr noch zusätzlich ein Bsp-Programm zeigen :). Wäre sehr cool.

Danke im voraus!

mfg

Googlehupf
 
Zuletzt bearbeitet:
Duruch das Implements sagst du der Klasse, dass sie ein Interface implementieren soll, soweit hast du das ja verstanden. Implementieren ist letzten Endes nicht viel was anderes als erben, mit leeren Methodenkörpern. Das bedeutet, dass ein Interface dazu gedacht ist Ordnung in ein Programm zu bringen und/ oder sicherzustellen, dass eine spezielle Methode vorhanden ist.
Das beste Beispiel sind da immer die Listener. Wenn du zum Beispiel einen ActionListener hast, übergibst du der Methode addActionListener, eine Klasse die ActionListener implementiert. Dadurch wird sichergestellt, dass die Methode actionPerformed gesetzt wurde und somit im Hintergrund weitergearbeitet werden kann.

Bei deinem ersten Beispiel ist es so, dass Byable ein Interface ist, dass einen leeren Methodenkopf getPrice hat. Dadurch, dass du Byable übergibst (du kannst keine Interfaces übergeben, nur Klassen) muss ein Objekt erstellt werden, dass Byable implementiert. Das bedeutet in deinem Beispiel, dass du nicht nur das Object "Car" übergeben könntest, sondern auch Truck, Motorbike oder eine annonyme Klasse. Bsp für annonyme Klasse:
Java:
CarDealer cd = new CarDealer();
cd.buyBuyable(new Buyable() {
   @Override
   public int getPrice(){
      return 1000;
   }
});
Diese Schreibweise verwendet man bei Listenern gerne mal, wenn sie nur eine oder wenige Aufgaben erfüllen sollen.

"this" ist nicht die Klasse (also das Konstrukt für das Object) sondern das bereits erzeugte Object. Damit übergibst du sozusagen, die Speicheradresse des Objektes.

addAdjustmentListener(new Scrollbar_Listener());//frage nebenbei: theoretisch könnte man hier auch ein this. machen //oder? Man brauchst aber nicht, weils eh eindeutig ist, dass die Klasse "Label_Scrollbar" gemeint wird, richtig?
nein kann man nicht. Wie gesagt, this verweist auf den Speicherort des eigenen Objektes. Wenn du "new" verwendest, wird ein neues Objekt erzeugt und somit ein komplett anderer Speicherort verwandt. Außerdem wäre es nicht möglich, weil diese Klasse nicht Scrollbar_Listener implementiert und somit gar keine gültige Übergabe wäre.

Ich hoffe ich konnte helfen, ist schon etwas spät und ich hoffe es war noch verständlich ;)
 
Ok, danke :D.

Zum this:

Schau mal, wenn man einen button_listener erzeugt dann macht man folgendes:
Java:
JButton button = new JButton();
button.addActionListener(new ButtonListener());

Und darum sage ich ja das man bei meinem Fall auch ein this machen kann, weil man ja eine ActionListener adden will, von dem Objekt das in einer anderen Klasse Instanziert wurde(also new).

Java:
//Steht in Klasse1:
Label_Scrollbar bar = new Label_Scrollbar(); //instanzieren

//Steht im Konstruktor von Label_Scrollbar, der durch die Instanzierung aufgerufen wird:
this.addAdjustmentListener(new Bar_Listener()); //das this jetzt, weil man von der Klasse "Label_Scrollbar" einen AdJustmentListener adden will bzw. halt erzeugen. Und naja das geht halt auch ohne this.

Ich finde das ja logisch, muss doch so stimmen wie ich es erklären und ich habs auch mit this. probiert es funktionert --> Mit und ohne this.

Der AdJustmentListener steht natürlich in der Klasse Label_Scrollbar.

Zum Interface:
In einer anderen Klasse rufe ich jetzt: carDealer.buyBuyable(new Car()); auf.

In wieder einer anderen Klasse ist folgende Methode:
Java:
 public void buyBuyable(Buyable b) { 
        billingAmount += b.getPrice();
    }

Bei dem Übergabeparameter geschieht im Prinzip folgendes:

Java:
Buyable b = new Car();
<-- Was passiert da genau?

Und wenn ich jetzt mace b.getPrice();, wie weiß der Compiler(oder der PC, wie auch immer das heißt) das er jetzt in die Klasse Car gehn muss und nicht in Truck oder sonst was?

Java:
//Normalerweise macht man ja: 
JButton button = new JButton(); 

//--> Also:
 Klasse name = new Klasse()

//Oben hingegen macht man:
Interface name = new Klasse()

Und naja was passiert jetzt genau da?
 
Mit dem "this" hast du natürlich recht, ich hatte dich falsch verstanden, ich dachte du wolltest es Anstelle des "new ButtonListener()" setzen. Davorsetzen kannst du es, ist aber (wie du richtig sagtest) überflüssig, da es eindeutig ist.

Ja du hast ebenfalls Recht, dass "Byable b = new Car()" gilt. Das ist aber genau das, was ich versuchte zu erklären ;)
Du hast sicher schon mit Vererbung gearbeitet, da Interfaces grundsätlich nach Vererbung erlernt werden. Daher weißt du dass folgendes möglich ist:
Java:
// Klasse 1:
class Eltern{
   int elternattribut = 0;
}

// Klasse 2 erbt von Klasse 1:
class Kinder extends Eltern{
   int kinderattribut = 1;
}

class Testklasse{
   public Testklasse(){
      // hier das wichtige: man erstellt ein Elternobjekt mit nur den Eigenschaften des Kindobjektes und den leer initialisierten des Elternobjektes (etwas verwirrend, aber versuch das zu verstehen)
      Eltern eltern = new Kinder();
   }
}

Etwas sehr ähnliches passiert bei deinem Beispiel:
Du erstellt ein Objekt, welches von dem Interface Buyable "erbt" (stimmt nicht ganz, aber ist erstmal unwichtig). Das ist dein Kinderobjekt und hat die Eigenschaften des Elternobjektes, nämlich die Methode getPrice() (wieder sehr ungenau, aber als erklärung gut). Somit hat Car jetzt diese Methode, da sie aber leer ist, muss sie überschrieben werden. Dafür ist das @Override gedacht.
Jetzt gibst du das Objekt der Zuweisung des Elternobjektes Buyable und hast damit deine volle Implentierung.
 
Der Vergleich mit dem erben von Klassen hinkt schon stark und man sollte sich daran nicht so festhalten, weil das für den späteren Entwurf von Programmen problematisch wird.
Wichtig ist zu wissen, dass ein Interface ein Kontrakt ist, also ein Vertrag zwischen einem Nutzer (Client) und einem Anbieter (Server). Im Prinzip hat jede Klasse auch ein implizites Interface ohne eine "Java-Interface" zu implementieren. Und zwar in Form der public methoden.
Warum also sollte man überhaupt Interfaces nutzen und implementieren? Nun, der Hauptgrund ist das Entkoppeln von der eigentlichen Implementierung. Es ist und sollte egal sein, wie der Vertrag erfüllt wird, sprich wie die eigentliche Implementierung aussieht.
Weiterer großer Vorteil: Austauschen der Implementierung zur Laufzeit

Ich empfehle am besten noch ein bisschen Literatur zu wälzen.
 
Danke ich glaube ich habs jetzt :).

Mein 2tes Beispiel, hier wird auch ein Interface angewendet, aber es zeigt nicht wirklich den richtigen Vorteil, es ist eher eine andere Lösung des Programmes richtig?

Das 1te Beispiel hingegen zeigt das nur eine Methode für kaufen von 3 verschiedenen Fahrzeugen nötig ist --> Vorteil der Interfaces.

"Buyable b = new Car()" --> Erzeugt im Prinzip nur ein Objekt von Car das Buyalbe implementiert und man kann nur die Methoden nutzen die im Interface Buyable stehn.

Hab ich das alles richtig verstanden?
 
@socke77: Ist schon klar, dass der Vergleich hinkt, aber als Erklärung finde ich den Weg immer recht praktisch. Genaueres lernt man durch anwenden kennen - so war es zumindest bei mir.

@Googlehupf: Schon richtig, mit der Ausnahme, dass dein 2. Beispiel genau dasselbe Prinzip benutzt, da der Observer im Hintergrund die Methoden braucht um weitzuarbeiten. Es ist jedoch für den Anwender nicht sichtbar und somit auch nicht anschaulich als Erklärung geeignet ;).
das erste Beispiel ist zwar simpel, aber selbsterklärend und somit besser geeignet ;)
 
Java:
public class Label_Scrollbar extends JScrollBar {
	public static final int SCHWER = 2;
	public static final int MITTEL = 1;
	public static final int LEICHT = 0;
	

	LevelChangeObserver cb;
	private int level;
	
	public Label_Scrollbar(int level, LevelChangeObserver cb) {
		super(JScrollBar.VERTICAL, 1, 1, 0, 3);
		this.cb=cb;
		this.level=level;
		addAdjustmentListener(new Scrollbar_Listener());
		color_Change();	
	}

Also hier mit super(...) ruft man den kunstruktor von JScrollbar auf bzw. stellt halt das ganze ein, also einen Scrollbar.

In eine anderen klasse, wo auch Label_Scrollbar instanziert wird, mache ich: contentPane.add(sb_level, BorderLayout.EAST);
Und contentPane ist halt ein BorderLayout(). Warum brauche ich hier ein gridLayout im folgenden Programm brauche ich es ja auch?

Java:
  private void FrameInit() throws Exception {
    contentPane = (JPanel) getContentPane();
    contentPane.setLayout(new BorderLayout());
    setSize(new Dimension(400, 300));
    setTitle("Frame Title");
    
    p_center = new JPanel();
    contentPane.add(p_center, BorderLayout.CENTER);
    JPanel p_east = new JPanel(new GridLayout(1,3));
    contentPane.add(p_east, BorderLayout.EAST);
    
    sb_red = new JScrollBar(JScrollBar.VERTICAL,100,10,0,265);
    sb_green = new JScrollBar(JScrollBar.VERTICAL,100,10,0,265);
    sb_blue = new JScrollBar(JScrollBar.VERTICAL,100,10,0,265);

    SB_Listener sbl = new SB_Listener();
    
    sb_red.addAdjustmentListener(sbl);
    sb_blue.addAdjustmentListener(sbl);
    sb_green.addAdjustmentListener(sbl);
    
    p_east.add(sb_red);
    p_east.add(sb_green);
    p_east.add(sb_blue);
  }
}

GridLayout ist ja dafür da, das Sachen in die Länge gezogen werden? Aber macht das nicht BorderLayout auch irgendwie? Was ist der genaue Unterschied?

Dieses 1,3 steht für: 1 Reihe und 3 Spalten oder?

Und kurz nochmal zum Interface zurück:
Das Programm mit dem LabelScroll_bar, das kann man leicht ohne interface auch machen, also was für Vorteile hat es in diesem Programm? Eigentlich gar keine. Der Lehrer wollte uns wahrscheinlich nur zeigen wie so ein interface ausssehen kann, richtig?

Danke!

mfg
 
Zuletzt bearbeitet:
Zurück