# Wozu sind Interfaces gut?



## Reality (20. Mai 2004)

Hi,
ich habe mir verschiedene Quellen über Interface durchgelesen, aber es will einfach nicht in meine Birne rein, für was das gut ist!

Mein Wissensstand:
- Wenn man ein Interface in eine Klasse implementiert, kann man keine Instacz erzeugen.
- Die Methoden im Interface müssen kein Körper haben (wozu gibt´s abstract?!)
- Man kann kein Konstruktor in Interface einbauen 
- Mehrere Klassen können die Methoden des Interfaces implementieren und es auf ihre Wünsche anpassen (was hindert mich daran eigene Methoden zu erstellen?!)

Besonders der letzte Punkt soll die Mehrfachvererbung in C++ ersetzen, aber ich sehe nur, wie man Methoden ohne Körper vererben kann (was auch mit abstract möglich ist) und um sie anschliessend in einer anderen Klasse zu initialisieren (was bringt das) und in einer anderen Klasse die Methode des Interfaces auch anders initialisieren kann.

Wozu braucht man das? Man kann doch den Konstruktor einer Superklasse überschreiben!

Liebe Grüße
Reality


----------



## Jaraz (20. Mai 2004)

Durch Vererbung spezialisierst du Klassen.

Mit einem Interface kannst du erreichen das im Grunde vollkommen verschiedene Objekte eine oder mehrere gemeinsame Verhaltensweisen besitzen.

Beispiel:

Object Auto und Object Dienstleistung
Beide eigentlich vollkommen verschieden, aber nun möchtest du ein Haushaltsbuch führen. Dieses Haushaltsbuch enthält eine Methode addPosten(Posten p).

Wie kannst du es nun erreichen, das du addPosten ein Auto und eine Dienstleistung hinzufügen kannst?

Entweder du leitest beide von Posten ab, was schwer werden könnte, weil die beiden wahrscheinlich vollkommen verschiedene Superklassen haben. z.b. Fahrzeug und Vorgang.
Oder du schreibst ein Interface Posten mit z.b. der Methode public double getKosten(); Dieses Interface implementierst du bei beiden Klassen und kannst somit alle Objekte der beiden Klassen, mit der Methode addPosten übergeben.

Abschließend kannst du z.B. über ein PostenArray im Haushaltsbuch laufen und mit der Methode getKosten() deine Ausgaben addieren.

Fazit:
Solange 2 Klassen nicht stark voneinander abhängig sind, sind Interfaces die elegantere Methode Gemeinsamkeiten zu definieren.

Abstract besagt einfach nur das die Klasse oder das Interface so nicht funktionieren und weiter spezialisiert werden müssen.

Gruß Jaraz


----------



## Reality (20. Mai 2004)

Hi Jaraz!
Danke, jetzt habe ich es besser verstanden! 

Liebe Grüße
Reality


----------



## bygones (20. Mai 2004)

Mein lieblingsbeispiel eines Interfaces ist das Interface Comparable.

Wie schon richtig gesagt dient ein Interface dazu eine Schnittstelle zu definieren. Wenn du versch. Objekte hast die ein und das selbe Interface implementieren musst du dich nicht kümmern, wie die einzelnen Objekte realisiert sind - was du weißt ist, dass sie alle das Interface implementieren und daher z.b. eine bestimmte Methode haben...

Am Bsp Comparable:

In der Datenstruktur TreeSet werden Objekte sortiert in eine Art Liste eingefügt. Die Frage ist nun woher weiß das TreeSet wie die Objekte sortiert werden müssen - die Antwort ist einfach: Alle diese Klassen müssen das Interface Comparable implementieren - das verlangt, das die Methode compareTo implementiert wird die sagt ob ein Objekt größer, kleiner oder gleich einem anderen ist.

Somit ist dem TreeSet gelinde gesagt schnurz egal was für Objekte es sortieren soll bzw. vor allem wie die einzelnen Objekte sortiert werden - es weiß nur, es gibt eine compareTo Methode und die sagt mir wie ich sortieren soll.

Wie oben gut gesagt, sie dienen dazu (untersch.) Objekten eine gemeinsame Eigenschaft zu geben !


----------



## bygones (20. Mai 2004)

Eine Sache noch bei der Interfaces ihre Genialität zeigen:

Stell dir vor du hast ein Programm das Daten aus einer Datenbank importiert. Das schreibst du auch so in dein Programm. Nun benutzt jemand dein Programm, hat keine Datenbank und würde gerne seine Daten aus einer Datei (Flatfile) importiere --> Das Programm muss komplett umgeschrieben werden.
Der nächste der es nutzen will hat nun wieder eine andere Art von Datenquelle --> wieder muss alles geändert werden.

Arbeitest du mit Interfaces hast du keine Probleme damit. Du sagst einfach:
"Jede Klasse die Daten für mein Programm bereitstellen will muss das XYZ Interface implementieren".

In dem Programm schreibst du dann nur das Interface als Datenbeschaffer und nicht deine Datenbankklasse.
Wenn jetzt einer mit einem Flatfile kommt, muss er nur eine Klasse schreiben die das Interface implementiert und schwupps läuft alles ohne das Hauptprogramm anzufassen  :roll: 

Wunderbare Sache dein programm flexibel und leicht erweiterbar zu machen....


----------



## Reality (21. Mai 2004)

Kleine Frage: 
Wenn zwei unterschiedliche Klassen geladen werden mit demselben Methoden-Namen, dann geht das doch auch?!

In meinem Buch habe ich Beispiele, die ich mit der obigen genannten Möglichkeit verwirklichen könnte.

Liebe Grüße
Reality


----------



## Beni (22. Mai 2004)

Es gibt dann einfach nur eine Methode. D.h. egal wie die Klasse angeschaut wird, es wird immer nur diese eine Methode aufgerufen.

Das funktioniert natürlich nur gut, wenn die Methode in beiden Interfaces dasselbe machen sollte.

Folgendes Beispiel funktioniert nur auf den ersten Blick:

```
public interface A{
  // String herstellen, der nur aus "A" und "a" besteht
  public String createString();
}
```


```
public interface B{
  // String herstellen, der nur aus "B" und "b" besteht
  public String createString();
}
```


```
public class C implements A, B{
  public String createString(){
    ... // was soll jetzt hier geschehen? Das widerspricht sich doch.
  }
}
```

Sollten die Methoden gleichheissen, aber einen anderen Rückgabewert haben (z.B. _public int createValue()_ und _public float createValue()_), kann man nicht mal mehr kompilieren.


----------



## Reality (22. Mai 2004)

Nein, du hast mich falsch verstanden. Ich meinte das ganze ohne Interface zu machen.


```
class A
{
  public test()
  {
  Individueller Code
  }
} 

class B
{
  public test()
  {
  Anderer individueller Code
  }
} 

class Tetster
{
  public static void main (String args[])
  {
  A a= new A();
  B b= new B();
  
  a.test();
  b.test();
  }
}
```

Macht doch ungefähr dasselbe wie ein Interface?
2 gleichnamige Methoden, aber die Methoden machen verschiedene Dinge.

Liebe Grüße
Reality


----------



## Beni (22. Mai 2004)

Sorry, lesen sollte man können  :roll: 

Also: nehmen wir mal an, irgendwo gibt es eine Methode, die "test()" benötigt.
Wenn man das A und das B so nimmt, wie Du geschrieben hast, muss man einmal "runTest( A a )" und einemal "runTest( B b )" schreiben.

Das ist viel Schreibarbeit, und schlecht erweiterbar (wenns jetzt noch Klasse C, D, E, ... gibt, huiii... ).

Der Vorteil von einem Interface ist, dass man nur noch ein "runTest( TestInterface ti )" schreiben muss.


Bis auf die Tatsache dass A und B "test" besitzen, haben sie nichts gemeinsam. Ebensogut könnte A eine Methode "blupp" und B "judihui" haben, es würde keinen Unterschied machen.


----------



## Reality (22. Mai 2004)

Hallo,


			
				Beni hat gesagt.:
			
		

> Wenn man das A und das B so nimmt, wie Du geschrieben hast, muss man einmal "runTest( A a )" und einemal "runTest( B b )" schreiben.


Hoffentlich nerve ich nicht, wenn ich frage, was du mit "run Test(B b)" meinst.


> Das ist viel Schreibarbeit, und schlecht erweiterbar (wenns jetzt noch Klasse C, D, E, ... gibt, huiii... ).



Entweder liefert das Buch keine guten Beispiele oder ich kapier das nicht:

Ich habe ein Interface mit den Methoden push() und pop() geschrieben, die dann auch in anderen Klassen initialisiert wurden und so sieht das dann im Beispiel-Code aus, wenn die geladen werden. Meiner Meinung nach ist das noch mehr Code:



```
//Erzeuge eine interface-Variable und greife über diese auf Stacks zu

class IFTest3 {
  public static void main(String[] args) {
  //Erzeuge eine Schnittstellen-Verweisvariable
  IntStack mystack;
  DynStack ds= new DynStack(5);
  FixedStack fs = new FixedStack(8);

  mystack = ds; //Lade dynamischen Stack
  //Lege einige Zahlen auf dem Stack ab
  for(int i=0; i<12; i++) mystack.push(i);

  mystack = fs; //Lade festen Stack
  for(int i=0; i<8; i++) mystack.push(i);

  mystack = ds;
  System.out.println("Werte im dynamischen Stack: ");
  for(int i=0; i<12; i++)
    System.out.println(mystack.pop());

  mystack = fs;
  System.out.println("Werte im festen Stack: ");
  for(int i=0; i<8; i++)
    System.out.println(mystack.pop());
  }
}
```

Liebe Grüße
Reality


----------



## Beni (22. Mai 2004)

1. runTest( B b ): "_Run_ Methode _test _von _b_ (einem Objekt vom Typ B)"

2. Es ist nur auf den ersten Augenblick mehr Code:
Beantworte kurz die Fragen im Quellcode.

```
mystack = ds;

// #######
// Kannst du sagen, was mystack jetzt ist (dynamisch oder fest)? Hätte die Antwort (dynamisch oder fest) eine Bedeutung?

  System.out.println("Werte im dynamischen Stack: ");
  for(int i=0; i<12; i++)
    System.out.println(mystack.pop());

  mystack = fs;

// #######
// Kannst du sagen, was mystack jetzt ist (dynamisch oder fest)? Hätte die Antwort (dynamisch oder fest) eine Bedeutung?

  System.out.println("Werte im festen Stack: ");
  for(int i=0; i<8; i++)
    System.out.println(mystack.pop());
```

Es ist beides mal: "Mit viel Aufwand könnte man es herausfinden, aber es hat keine Bedeutung".

Es ist zweimal derselbe Code (for... println), der aus einem Stack ausliest, und Ergebnis ausdruckt.
Egal ob es ein dynamischer, ein fester oder sonst ein Stack ist: der Code um einen Stack auszulesen bleibt gleich, unabhängig wie der Stack aufgebaut ist.

Der Witz daran ist, dass ein Stück Code fertig geschrieben ist, und *nie mehr verändert werden muss*.


----------



## Reality (22. Mai 2004)

Hi Beni!
Es ist mir jetzt klarer. Dann sind Interfaces besonders geeignet, wenn man den Code weiterreicht oder in einem anderen Projekt wiederverwenden will?

Liebe Grüße
Reality


----------



## Beni (22. Mai 2004)

Reality hat gesagt.:
			
		

> Dann sind Interfaces besonders geeignet, wenn man den Code weiterreicht oder in einem anderen Projekt wiederverwenden will?









Es muss nichteinmal ein anderes Projekt sein. Schon wenn ein eigenes Projekt genug gross ist (ich meine damit alles mit mehr als 20 Klassen), lohnt sich der Einsatz von Interfaces.


----------



## Tobias (22. Mai 2004)

Noch mal zu deiner Frage, ob es nicht auch ginge, wenn einfach zwei Klassen den selben Methodennamen benutzen... - ja, das geht:


```
class A { 
    methode() {
        // Implementierung 1
    }
}

class B {
    methode() {
        // Implementierung 2
    }
}
```

ABER: Du kannst niemanden dazu zwingen, eine Methode methode() in seine Klasse einzubauen. Und - noch schlimmer - die Klassen A und B besitzen keinen gemeinsamen Obertyp, das heißt, dass du zum Beispiel nicht verschiedene Instanzen von A und B in eine Collection packen, aufrufen und dann die Methode methode() aufrufen kannst - das läßt der Compiler nicht zu (denn, auf welches Objekt soll er den Casten? auf A oder auf B?).
Mit Interfaces steht ein gemeinsamer Obertyp zur Verfügung (der des Interfaces), obiges Szenario ist damit kein Problem mehr. 
Und man kann fremde Programmierer dazu verdammen, die gewünschten Methoden zu implementieren  :bae:!

mpG
Tobias


----------



## Reality (22. Mai 2004)

OK, danke für eure Geduld!


----------

