Forum: PC-Programmierung Java Interfaces - als Objekte nutzen


von AndyS (Gast)


Lesenswert?

Hallo liebe Freunde,

Habe folgendes Verständnisproblem:

Ich weiß wozu interfaces gut sind und wie sie verwendet werden!
Ich habe hier folgendes Beispiel aus dem V2B Training:
1
package dateiarbeit;
2
3
import java.nio.file.Path;
4
import java.nio.file.Paths;
5
6
/**
7
 *
8
 * @author AndyS
9
 */
10
public class Dateiarbeit {
11
    
12
    public static void main(String[] args) {
13
        
14
        String path = System.getProperty("user.home");
15
        
16
        Path verzeichnis = Paths.get(path);
17
        System.out.println("Verzeichnis: " + verzeichnis.toString());
18
    }
19
}

Das Interface Path wird hier als nicht instanziertes Objekt verwendet. 
Wieso funktioniert das aber ohne weiteres?

Das Interface ist als folgendes deklariert:

public interface Path extends Comparable<Path>, Iterable<Path>, 
Watchable

Es erbt dir Eigenschaften der Interfaces Comparable, Iterable, und 
Watchable.

Was bedeuten aber diese Spitzen Klammern daneben?

Die Entscheidende Frage: Wieso lässt sich ein Interface als 
Objektvariable nutzen?

Ist da sprinzipiell mit jedem Interface möglich?

von Florian (Gast)


Lesenswert?

AndyS schrieb:
> Das Interface ist als folgendes deklariert:
>
> public interface Path extends Comparable<Path>, Iterable<Path>,
> Watchable
>
> Es erbt dir Eigenschaften der Interfaces Comparable, Iterable, und
> Watchable.
>
> Was bedeuten aber diese Spitzen Klammern daneben?

Das sind Java Generics.

Und das ganze scheint ein Beispiel für das aus C++ bekannte, aber selten 
verwendete "curiously recurring template pattern" zu sein.

> Die Entscheidende Frage: Wieso lässt sich ein Interface als
> Objektvariable nutzen?

Weil das ein Hauptanwendungsgebiet ist?

> Ist da sprinzipiell mit jedem Interface möglich?

Ja.

von AndyS (Gast)


Lesenswert?

Florian schrieb:
> Weil das ein Hauptanwendungsgebiet ist?

Hmm, ich dachte Interfaces werden vorwiegend dazu verwendet um bestimmte 
Methoden in einer Klasse implementieren zu lassen bzw. wie in abstrakten 
Klassen als Grundgerüst einer Klasse zu dienen?

Ich habe im Net noch kein einziges Beispiel bei der Erklärung der 
Interfaces gefunden wo der Name des Interfaces vor einem Namen eines 
Variablentyps des gleichen ist.

von Stefan T. (tommie)


Lesenswert?

AndyS schrieb:
>
1
>         Path verzeichnis = Paths.get(path);
2
>
>
> Das Interface Path wird hier als nicht instanziertes Objekt verwendet.
> Wieso funktioniert das aber ohne weiteres?

Meinst du "Path.get"? Das wird eine statische Methode sein.
Oder was meinst du?

von AndyS (Gast)


Lesenswert?

Stefan Tomanek schrieb:
> Meinst du "Path.get"? Das wird eine statische Methode sein.
> Oder was meinst du?

Nein, Paths.get ist die statische Methode der Klasse Paths.
Ich meine |--> Path verz <--| = ...

von hmmm (Gast)


Lesenswert?

Das was Paths.get() zurückgibt hat das Interface, folglich kann man es 
hier verwenden. Hat den Vorteil das man nicht wissen muss was für ein 
Objekttyp es genau ist, sondern nur fordert dass es das interface hat 
(freier als einen festen Typ fordern, gleichzeitig aber sichergestellt 
dass das Interface passt)

von AndyS (Gast)


Lesenswert?

Versteh ich nicht ganz was du damit meinst.

Gilt nicht prinzipiell, dass mann abstrakte Klassen nicht erstellen 
kann. Da Interfaces im Prinzip abstrakte Klassen sind widerspricht sich 
das irgendwie. Von der Logik her leuchtet es mir überhaupt nicht ein 
wieso ein Interface einen Wert annehmen kann.

von vorbeigeschaut (Gast)


Lesenswert?

>Gilt nicht prinzipiell, dass mann abstrakte Klassen nicht erstellen
kann.

Weder mann noch eine Frau kann abstrakte Klasse instantiieren - sonst 
wären sie nicht mehr abstrakt ;) Das wird auch im Beispiel nicht 
versucht.

> Die Entscheidende Frage: Wieso lässt sich ein Interface als
> Objektvariable nutzen?
>
> Ist da sprinzipiell mit jedem Interface möglich?

Weil ein Interface - genau wie eine (abstrakte) Klasse - eben ein Typ 
ist. Das ist genau Sinn und Zweck der Geschichte.

Path myVariable = Paths.get(strPath);

Man deklariert da eine lokale Variable von dem Typ (Path ) und weist ihr 
eine Instanz (dieses Typs) zu, die von der statischen Methode (get) 
einer anderen Klasse (Paths) instantiiert und zurückgegeben wird.

Was im Beispiel etwas verwirrend ist ist die String path -Variable, die 
mit dem ganzen nur begrenzt zu tun hat und deswegen unglücklich benannt 
wurde :) Diese habe ich in strPath umbenannt.

von AndyS (Gast)


Lesenswert?

vorbeigeschaut schrieb:
> Man deklariert da eine lokale Variable von dem Typ (Path ) und weist ihr
> eine Instanz (dieses Typs) zu

Genau das verstehe ich ebeb nicht, denn damit instanziert man ja ein 
Interface.

Verstehen würde ich es wenn die Klasse Paths das Interface Path 
implementiert und man das ganze so:

Path path = new Paths();
path.set(string_path);
und über path.get() bekomme ich dann den Pfad.

Aber so funktioniert es nicht, kann es auch nicht.

Aber eine Regel sticht aus deiner Erklärung irgendwie hervor:
Wenn ich Interfaces als Objektvariablen nutzen will muss ich diese über 
Funktionen initialisieren./?

Objektvariablen sind es aber dann trotzdem ob durch "new" erstellt oder 
einer Funktion.

Ich kann ja auch eine Abstrakte Klasse so nicht initialisieren, also 
verstehe ich nicht ganz.

von vorbeigeschaut (Gast)


Lesenswert?

Okay... eine nach dem anderen...
> Ich habe im Net noch kein einziges Beispiel bei der Erklärung der
> Interfaces gefunden wo der Name des Interfaces vor einem Namen eines
> Variablentyps des gleichen ist.

Was dich anscheinend verwirrt, sind die Namen. In Java gibt es eine 
Namenskonvention:

Interface/Klassen -> GrOß
Package/Member/Variablen -> kLeIn

Von daher sind die Konstrukte wie:
1
FooBarFactory fooBarFactory = new FooBarFactory ();
2
Bar barFromFoo = fooBarFactory.getBar();
einfach die Norm. Aus OOP-Sicht ist völlig unerheblich, ob Foo ein 
Interface oder eine Klasse ist. In beiden Fällen ist das ein Typ und so 
darf (und muss!) man ihn für die Variablen- (wie auch für die Parameter- 
sowie Rückgabetyp-) Deklarationen verwenden.
1
InterfaceName variablenName = ...;
2
3
private InterfaceName myMethod(){
4
    ...
5
}
6
7
public void anotherMethod(InterfaceName var){
8
    if(var != null){
9
        ....
10
    }
11
}

Die hartnäckige Pascal-Fans benennen die Interface historisch mit "I" 
(was in Java nicht notwendig, aber auch nicht verboten ist), damit man 
sie von den Klassen optisch unterscheiden kann, etwa:
1
FooBarFactory  fooBarFactory = new FooBarFactory();
2
IBar barFromFoo = fooBarFactory.getBar();
3
...
4
barFromFoo.doSomething();
JDK (von wo java.nio.file.* kommen ) hat nie dieser Konvention gefolgt.

Eine weitere Kleinigkeit. Die Bezeichner wie "verzeichnis" sind 
spätestens nach der Grundschule Tabu :) Man muss immer an die Kollegen 
denken, die den Code evtl. später pflegen sollen... also, in Englisch!

Jetzt zu der eigentlichen Frage. Vergiss mal die abstrakten Klassen, 
Methoden etc. und merke folgendes:
Ein Interface wird (von einer Klasse) IMPLEMENTIERT.
Eine konkrete Klasse wird INSTANTIIERT.
Eine Variable wird DEKLARIERT.
Einer bereits deklarierten Variable wird ein Wert vom passenden Typ 
ZUGEWIESEN.

Jetzt schaue mal das Beispiel erneut an und versuche zu finden, was wo 
gemacht wird.

von AndyS (Gast)


Lesenswert?

Oje. So langsam wird das ganze doch kompliziert.

vorbeigeschaut schrieb:
> Ein Interface wird (von einer Klasse) IMPLEMENTIERT.
> Eine konkrete Klasse wird INSTANTIIERT.
> Eine Variable wird DEKLARIERT.

Das weiß ich doch und deswegen verstehe ich nicht wieso ich den 
Interface intitialiseren muss.
Das problem ist, dass die Klasse Paths das Interface Path gar nicht 
implementiert.

Was noch möglich wäre ist dass diese Methode der Klasse Paths ein Path 
Objekttyp zurückgibt, welches dann einfach in die Variable geschrieben 
wird. Dann frage ich mich aber wie dieses Path Objekt, dass eigentlich 
in der Methode Paths.get() zurückgegeben wird initialisiert wurde wenn 
es nur ein Interface ist.

Wahrscheinlich wirst du wieder das hier schreiben:
1
IBar barFromFoo = fooBarFactory.getBar();

Wie ist aber in der Methode getBar ein barFromFoo Objekt instanziiert 
worden wenn es ein Interface ist?

Auf was ich hinaus will ist, dass mir schon einleuchtet, dass ich eine 
!Klasse! durch eine Funktion, welche selbes Objekt zurückgibt, 
instanzieren kann. Eh klar, denn in der Methode wird ein Objekt des 
gleichen mit new instanzieert und dann der neuen Variablen 
zurückgegeben.

Mir ist jedoch immer noch nicht klar wie ich in der Methode getBar bzw. 
getPath das Interface initialisiere und wie sinnvoll es eigentlich ist 
diese einer Interfacevariablen zu übergeben.
Denn ein Interface ist eine Abstrakte Klasse und kann dementsprechend 
auch nicht veränderbare Felder, Funktionen etc... haben

Verstehst du meinen Ansatz?

von AndyS (Gast)


Lesenswert?

Ich denke ich habe es jetzt begriffen!

In der doc steht es zwar bei der get Funktion nicht explizit dabei, aber 
das ist ja der Sinn und Zweck der OO.

Normalerweise kann ich durch die Polymorphie folgendes sagen:

InterfaceName Var = new KlassenNameWelchesDasInterfaceImplementiert();
Var ist demnach ein Objekt vom Typ 
KlassenNameWelchesDasInterfaceImplementi- ert()

Was hier passiert sein muss ist, dass das new 
KlassenNameWelchesDasInterfaceImplementiert() in der Methode get 
aufgerufen wird und als InterfaceName zurückgegeben wird.

Also hat mich hier das hin und her der Polymorphie etwss verwirrt. In 
wirklichkeit wird nämlich in der methode get auf eine Klasse 
zurückgegriffen welche die Schnittstelle Path implementiert und somit 
ist Path eine Objektvariable dieser eigentlich instanziereten Klasse, 
welche dem Entwickler unlogischerweise vorenthalten wird.

Meine Frage hierzu: Wieso implementiert man nicht gleich diese 
versteckte Klasse in Klassenliste des Packages?

Ein Wirr War für nichts und wieder nichts...

von vorbeigeschaut (Gast)


Lesenswert?

ja, klar. Der Knackpunkt ist, dass die Methode Paths.get("...") den 
Rückgabe-Typ absichtlich als Interface deklariert, da sie nicht verraten 
möchte, welche genau Klasseninstanz sie erzeugt und zurück gibt :) Für 
dich ist das auch egal... solange diese unbekannte Klasse X das besagte 
Interface implementiert, kann jede Instanz der Klasse deiner Variable 
zugewiesen werden. Ein klassischer Factory Patern.

von AndyS (Gast)


Lesenswert?

vorbeigeschaut schrieb:
> da sie nicht verraten
> möchte, welche genau Klasseninstanz sie erzeugt und zurück gibt :)

meiner Meinung nach Sinnlos. Sowas nenne ich Vergewaltigung der 
Interfaces weil das ja nicht der Sinn und Zweck der Sache ist.
Aber schon wieder ein neues Konzept dazugelernt!

Durch dich bin ich auf ddie Lösung gekommen, dafür danke!

von vorbeigeschaut (Gast)


Lesenswert?

AndyS schrieb:
> Wieso implementiert man nicht gleich diese
> versteckte Klasse in Klassenliste des Packages?

Weil in OOP außer Polymorphie noch die Kapselung gibt :) Die eigentliche 
Implementierung für Linux kann völlig anderes als die für Windows 
aussehen. Die Funktionalität ist aber (nach außen) stets gleich. So 
nimmt man ein Interface und versteckt dahinter die Einzelheiten.

Sinn der Sache ist, dass dein Code dann überall funktioniert. Es wäre 
falsch, die Klassen in JDK zugänglich zu machen, da sonst könntest du 
z.B. LinuxPath (statt Interface Path) nehmen (=statisch 
referenzieren)und sich wundern, warum unter Windows nix funktioniert :)

von vorbeigeschaut (Gast)


Lesenswert?

AndyS schrieb:
> Sowas nenne ich Vergewaltigung der
> Interfaces weil das ja nicht der Sinn und Zweck der Sache ist.

Sorry, aber dann hast du immer noch nicht annähernd verstanden, was Sinn 
der Sache bei den Interfaces ist :)

von AndyS (Gast)


Lesenswert?

vorbeigeschaut schrieb:
> Weil in OOP außer Polymorphie noch die Kapselung gibt :) Die eigentliche
> Implementierung für Linux kann völlig anderes als die für Windows
> aussehen. Die Funktionalität ist aber (nach außen) stets gleich. So
> nimmt man ein Interface und versteckt dahinter die Einzelheiten.
>
> Sinn der Sache ist, dass dein Code dann überall funktioniert. Es wäre
> falsch, die Klassen in JDK zugänglich zu machen, da sonst könntest du
> z.B. LinuxPath (statt Interface Path) nehmen (=statisch
> referenzieren)und sich wundern, warum unter Windows nix funktioniert :)

Scheiße, da hast du recht!! Blöd dass ich nicht so überlegt hab.
Meine Annahme war, dass die versteckte Klasse normal zugänglich wäre, 
demnach würde es keinen Sinn machen. Aber du hast sicher Recht damit, 
dass diese Klasse auf jedem OS anders ausschauen könnte, eh klar!

Passt!

von AndyS (Gast)


Lesenswert?

vorbeigeschaut schrieb:
> Sorry, aber dann hast du immer noch nicht annähernd verstanden, was Sinn
> der Sache bei den Interfaces ist :)

RIchtig, bis zu dem Zeitpunkt nicht, aber jetzt verstehe ich das 
Konzept.
Tatsache ist aber, dass ich diese Art Verwendung der Interfaces so 
niemals in meinen eigenen Klassen benötige, außer ich benutze inline 
Assembler oder ähnliches.

von hmmm (Gast)


Lesenswert?

Kann für deine Programme zutreffen. Aber so ungewöhnlich ist es nicht ;)

von AndyS (Gast)


Lesenswert?

Wieso? Wenn ich richtig überlege bräuchte man nicht einmal für die 
portierbarkeit interfaces, da mann ja auch statt ihnen dementsprechende 
unterschiedliche unsichtbare Klassen mit identischen Eigrnschaften 
erstellen kann.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

AndyS schrieb:
> Wieso? Wenn ich richtig überlege bräuchte man nicht einmal für die
> portierbarkeit interfaces, da mann ja auch statt ihnen dementsprechende
> unterschiedliche unsichtbare Klassen mit identischen Eigrnschaften
> erstellen kann.

Das hat nix mit Portierbarkeit zu tun (das kann man auch über abstrakte 
Klassen lösen) sondern damit, das man eine Bindung an eine Konkrete 
Implementierung verhindert.
In deinem Beispiel, kann es z.B. sein das du Path Objekte nicht nur von 
der Faktory sondern von ganz woanders bekommst, und derjenige könnte 
eine ganz andere Implementierung nutzen als die Pathfactory.
Die konkrete Instanz ist natürlich immer von einer Klasse welches das 
interface implementiert.

Auf die weise kann man sehr schön Abhängigkeiten im Code vermeiden und 
allgemeien Algorithmen oder Methoden schreiben, schau dir z.B. die 
Collection API an, da sieht man das sehr schön das viele Algorithmen in 
der Hilfsklasse "Collections" nie auf einem Konkreten Typen arbeiten und 
somit auf jede beliebige Implementierung des Interfaces arbeiten können.

Hatten wir hier aber auch schon mal: 
Beitrag "Java Interface"

von Florian (Gast)


Lesenswert?

AndyS schrieb:
> Wahrscheinlich wirst du wieder das hier schreiben:
> IBar barFromFoo = fooBarFactory.getBar();
>
> Wie ist aber in der Methode getBar ein barFromFoo Objekt instanziiert
> worden wenn es ein Interface ist?

Sortier mal deine Gedanken. Es gibt kein "barFromFoo-Objekt" (also 
Objekt vom Typ barFromFoo), barFromFoo ist der Name einer Variablen.

Du meinst vermutlich: "Wie ist aber ein IBar-Objekt erzeugt worden, 
obwohl IBar ein Interface ist?".

Antwort: Gar nicht. Es ist ein Objekt vom Typ Irgendwas erzeugt worden 
(mit class Irgendwas extends IBar). Das kann nun allen Variablen vom Typ 
Irgendwas oder auch allen Variablen vom Typ IBar zugewiesen werden.

Wie willst du sonst mehrere "zusammengehörige" Typen in einem 
heterogenen Container (wie Java und C++ nunmal normalerweise vorsehen) 
halten?

von AndyS (Gast)


Lesenswert?

Läubi .. schrieb:
> Auf die weise kann man sehr schön Abhängigkeiten im Code vermeiden und
> allgemeien Algorithmen oder Methoden schreiben, schau dir z.B. die
> Collection API an, da sieht man das sehr schön das viele Algorithmen in
> der Hilfsklasse "Collections" nie auf einem Konkreten Typen arbeiten und
> somit auf jede beliebige Implementierung des Interfaces arbeiten können.

Aber was macht es dann für einen Unterschied wenn ich in jeder 
unabhängigen Methode einer satic Klasse eine Klasse definiere welches 
das bestimmte Interface implementiert und dann den gewünschten Wert 
zurückgibt, oder übersichtshalber (meiner Meinung nach besser) die 
direkte Klasse durch Paths_ path = new Path_(str_path); initialisiere?

Es kann doch keiner abstreiten, dass die zweite Methode übersichtlicher 
ist und mehr über sich aussagt.

> Auf die weise kann man sehr schön Abhängigkeiten im Code vermeiden und
> allgemeien Algorithmen oder Methoden schreiben

Mit Abhängigkeiten meinst du warscheinlich die Implementierungen der 
jeweiligen Interfaces in der Hilfsklasse.
Naja würde man es mit der zweiten Methode lösen bräuchte man 
dementsprechend nur eine Implementierung bzw erweiterung, und das ist 
doch glaub ich nicht so unübersichtlich oder?

von AndyS (Gast)


Lesenswert?

AndyS schrieb:
> einer satic Klasse eine Klasse definiere welches

... einer static Klasse ein Objekt der richtigen Klasse definiere 
welches ...

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

AndyS schrieb:
> unabhängigen Methode einer satic Klasse eine Klasse definiere welches
> das bestimmte Interface implementiert und dann den gewünschten Wert
> zurückgibt

Das tut man auch nicht, das ist nur in deinem Beispiel so und ist 
einfach eine Möglichkeit. Hier einfach mal ein einfaches Beispiel am 
Fall "Runnable".
Ein Thread benötigt im Konstruktor ein Runnable:
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html#Thread%28java.lang.Runnable%29
Das ist alles was ein Thread wissen muss, nämlich das die Instanz die du 
ihm gibt eine Methode run() implementiert.
Der Aufrufer (also du) kann jetzt:
a) eine innere Klasse definieren:
1
Thread thread = new Thread(new Runnable() {
2
3
  @Override
4
  public void run() {
5
    System.out.println("Hello from inner class");
6
  }
7
});
8
thread.start();
b) eine Speziell für diesen Fall angelegte Klasse nutzen:
1
class PrimeRun implements Runnable {
2
    long minPrime;
3
    PrimeRun(long minPrime) {
4
        this.minPrime = minPrime;
5
    }
6
7
    public void run() {
8
        System.out.println("Calculating primes");
9
    }
10
}
11
...
12
Thread thread = new Thread(new PrimeRun(100));
13
thread.start();
c) selbst Runnable in deiner Klasse implementieren
1
Thread thread = new Thread(this);
2
thread.start();
d) selbst ein Runnable als Parameter erwarten
1
public void executeMe(Runnable runnable) {
2
  Thread thread = new Thread(runnable);
3
  thread.start();
4
}
e) ... weitere Möglichkeiten sind denkbar ...

All das Funktioniert, ohne das die Klasse "Thread" wissen muss welche 
Konkrete Instanz ihr nun übergeben wird. Natürlich könnte man sich jetzt 
das Runnable auch wieder von einer Factory abholen... Was die Factory in 
diesem Beispiel überhaupt soll musst du den Ersteller des beispiels 
fragen.

von vorbeigeschaut (Gast)


Lesenswert?

Läubi .. schrieb:
> Was die Factory in
> diesem Beispiel überhaupt soll musst du den Ersteller des beispiels
> fragen.

Das ursprüngliche Beispiel kommt höchstwahrscheinlich von JDK7. Dort (in 
java.nio) gibt es eine nützliche Utility-Klasse mit einer Menge 
statischen Factory-Methoden. Ich nahm an, dass genau das (Factory 
Pattern) verwirrt AndyS und konstruierte aus dem Kopf ein etwas 
abstrakteres FooBar -Beispiel. Er hat aber (anscheinend - immer noch) 
Schwierigkeiten mit dem eigentlichen Interface-Konzept.

von AndyS (Gast)


Lesenswert?

vorbeigeschaut schrieb:
> Er hat aber (anscheinend - immer noch)
> Schwierigkeiten mit dem eigentlichen Interface-Konzept.

Ich weiß, dass es durch die Polymorphie funktioniert, denn Interfaces 
sind ja sehr ähnlich wie abstrakte Klassen, und man kann auch eine 
Interface Schnittstelle für davon abgeleitete (Implementierende) Klassen 
als Objekte definieren, da ja Polymorphie.

Wieso jedoch das ganze umeinander, keine Ahnung. Für mich eig nicht 
relevant, da ich ja verstehe wie das Konzept funktioert, jedoch nicht 
weiß wieso es angewendet wird...

Läubi .. schrieb:
> a) eine innere Klasse definieren:Thread thread = new Thread(new Runnable() {
>
>   @Override
>   public void run() {
>     System.out.println("Hello from inner class");
>   }
> });
> thread.start();

Ich weiß noch nicht wie innere Klassen funktionieren, kann es mir aber 
schon vorausdenken.

Läubi .. schrieb:
> b) eine Speziell für diesen Fall angelegte Klasse nutzen:class PrimeRun 
>implements Runnable {
>     long minPrime;
>     PrimeRun(long minPrime) {
>         this.minPrime = minPrime;
>     }
>
>     public void run() {
>         System.out.println("Calculating primes");
>     }
> }
> ...
> Thread thread = new Thread(new PrimeRun(100));
> thread.start();

Ist klar!

Läubi .. schrieb:
> All das Funktioniert, ohne das die Klasse "Thread" wissen muss welche
> Konkrete Instanz ihr nun übergeben wird.

Das sehe ich anders. In allen varianten musst du nämlich ein neues 
Objekt erzeugen in welches die run() Methode überschrieben wird und dann 
übergibst du dieses auch.

von Läubi .. (laeubi) Benutzerseite


Lesenswert?

AndyS schrieb:
> Das sehe ich anders. In allen varianten musst du nämlich ein neues
> Objekt erzeugen in welches die run() Methode überschrieben wird und dann
> übergibst du dieses auch.

Dann siehst du das falsch ;-)
Natürlich muss das konkrete Objekt die Methode implementieren, aber 
"Thread" muss die konkrete Klasse nicht kennen.

AndyS schrieb:
> dass es durch die Polymorphie funktioniert, denn Interfaces
> sind ja sehr ähnlich wie abstrakte Klassen

Interfaces sind was anderes als Abstrakte Klassen, den unterschied kann 
man aber nicht einfach durch anstarren eines Beispiels erkenne, sondern 
das sind einfach zwei unterschiedliche Konzepte welche in der 
praktischen Anwendung sowohl ihre Vor- als auch Nachteile haben.

Ein Interface ist einfach ein Platzhalter für eine Klasse welche dieses 
Interface (oder mehrere) implementiert. Deshalb kannst du dieses als 
Typen benutzen anstelle der konkreten Klasse.

Es geht dabei auch in erster Linie nur um die Zusicherung von 
Eigenschaften, du sagst einfach damit aus:
1
"Das Objekt worauf diese Referenz zeigt hat (bzw. soll) die im Interface vereinbarten Methoden (haben)".
Dies wiederum nutzt der Compiler aus um zur Compilezeit zu prüfen das 
alles mit rechten Dingen zugeht.

Du könntest auch überall als Parameter "Object" nutzen und per 
reflection irgendwelche Methoden per Namen aufrufen und hoffen das das 
konkrete Objekt diese implementiert, das hat sich aber als Unpraktisch 
erwiesen ;-)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.