it-swarm.com.de

Die Bedeutung von Schnittstellen in Java

Nehmen wir an, wir haben zwei Klassen, Tiger und Aeroplane. Eine Sache, die für diese beiden Typen gemeinsam ist, ist die Geschwindigkeit. Ich weiß, dass es unlogisch wäre, eine Oberklasse ClassWithSpeed zu erstellen und dann Unterklassen Aeroplane und Tiger von ihr abzuleiten. Stattdessen ist es besser, eine Schnittstelle zu erstellen, die die Methode speed() enthält, und diese dann in Aeroplane und Tiger zu implementieren. Ich verstehe das. Aber wir können dasselbe auch ohne Schnittstellen tun. Wir könnten die Methode speed() in Aeroplane und die Methode speed() in Tiger. Definieren. Der einzige (möglicherweise sehr große) Fehler wäre, dass wir die Objekte von Tiger und Aeroplane nicht über eine Schnittstellenreferenz "erreichen" könnten.

Ich bin Anfänger in Java und OOP, und ich wäre sehr dankbar, wenn mir jemand die Rolle von Schnittstellen erklärt. Prost!

42
Want

Es ist:

public int howFast(Airplane airplane) {
    return airplane.speed();
}

public int howFast(Tiger tiger) {
    return tiger.speed();
}

public int howFast(Rocket rocket) {
    return rocket.speed();
}

public int howFast(ThingThatHasntBeenInventedYet thingx) {
    // wait... what? HOW IS THIS POSSIBLE?!
    return thingx.speed();
}

...

vs

public int howFast(Mover mover) {
    return mover.speed();
}

Stellen Sie sich jetzt vor, Sie müssen zurückgehen und all diese howFast-Funktionen in der Zukunft ändern. 

Interface oder nein, jede Klasse muss die speed()-Methode implementieren oder erben. Über eine Benutzeroberfläche können Sie diese unterschiedlichen Klassen leichter verwenden, da sie sich jeweils zu einem bestimmten Verhalten versprochen haben. Sie rufen speed() auf, und sie geben eine int zurück, sodass Sie keine separaten Methoden für jede mögliche Klasse schreiben müssen. 

Wenn Sie feststellen, dass Sie die Geschwindigkeit aufgrund eines Durchbruchs in der relativistischen Physik anders handhaben müssen, müssen Sie nur die Methoden aktualisieren, die speed() aufrufen. Wenn Ihre Urenkelin eine Klasse für HyperIntelligentMonkeyFish schreibt, muss sie Ihre alte Binärdatei nicht zerlegen und Änderungen vornehmen, damit Ihr Code ihre mutierte Armee überwachen und steuern kann. Sie muss nur den HyperIntelligentMonkeyFish implements Mover angeben.

70

Schnittstellen ermöglichen es Java, da es statisch typisiert ist, mehrfache Vererbungsbeschränkungen so umzugehen, wie es sich für die Sprachdesigner lohnt.

In einer dynamischen Sprache (wie Python, Ruby usw.) können Sie einfach die Geschwindigkeitsmethode für ein beliebiges Objekt aufrufen und zur Laufzeit feststellen, ob es dort ist oder nicht.

Java hingegen ist statisch typisiert, was bedeutet, dass der Compiler zustimmen muss, dass die Methode im Voraus vorhanden ist. Die einzige Möglichkeit, dies für Klassen zu tun, die keine gemeinsamen Vorfahren haben und möglicherweise nur Object gemeinsam haben, ist eine Schnittstelle.

Da Objekte eine beliebige Anzahl von Schnittstellen implementieren können, bedeutet dies, dass Sie die Güte der Mehrfachvererbung (ein einzelnes Objekt, das sich für verschiedene Methoden als mehrere verschiedene Objekte ausgeben kann) ohne den Nachteil (in Konflikt stehende Implementierungen in den beiden Superklassen) erhalten.

Mit Java 8 gelangten die Entwickler der Sprache zu dem Schluss, dass Schnittstellen ohne Implementierung zu restriktiv waren ( meine Lösung schätze ich nicht ;-)), sodass sie eine Standardimplementierung zulassen und somit die Erweiterung ermöglichen Multi-Vererbungsoptionen von Schnittstellen, wobei immer noch versucht wird, das widersprüchliche Implementierungsproblem über einen komplexen Satz von Vorrangregeln - zu vermeiden , sodass eine eindeutige Standardimplementierung ausgeführt werden muss.

8
Yishai

Ich versuche den Vorteil der Schnittstelle anhand des folgenden Beispiels zu erklären.

angenommen, Sie haben eine andere Klasse, in der Sie den Tiger oder das Flugzeug als Parameter verwenden müssen. Mit Hilfe der Schnittstelle können Sie also mit aufrufen

someObject.someMethod(ClassWithSpeed)

wenn Sie jedoch keine Schnittstelle verwenden, können Sie diese verwenden

someObject.someMethod(Tiger)
someObject.someMethod(AeroPlane)

Was solltest du jetzt tun? Ihre wahrscheinliche Antwort lautet: "I will use two overloaded method".

Das ist soweit okay, aber

Angenommen, Sie müssen weitere Optionen hinzufügen (z. B. Auto, Fahrrad, Kaninchen, Schildkröte ... 100 andere). Also, was werden Sie tun, um die Änderung Ihres vorhandenen Codes vorzunehmen? Sie müssen eine Menge Dinge ändern .. 

Das obige Gesamtbeispiel hat nur einen Zweck. Das heißt 

"Wir brauchen eine Schnittstelle, um ein besseres, wiederverwendbares und korrekt objektorientiertes Design zu erstellen."

N.B.  

  1. wenn Sie sich sicher sind, dass das Programm zu klein ist und Sie es nie ändern müssen, ist es in Ordnung, ohne Interface zu implementieren
6
stinepike

Durch das Definieren einer Schnittstelle können Sie Methoden definieren, die nicht nur für Airplane und Tiger funktionieren, sondern auch für andere Klassen, die dieselbe Schnittstelle verwenden.

Angenommen, Ihre Schnittstelle ist IObjectWithSpeed. Dann können Sie eine Methode wie diese definieren - in einer einzigen Klasse, die mit IObjectWithSpeed-Objekten arbeitet.

  public double calculateSecondsToTravel( IObjectWithSpeed obj, double distance ) {
       return distance / obj.getSpeed();
  }

Schnittstellen erlauben es uns, das open/closed-Prinzip zu erfüllen - offen für Erweiterungen, aber geschlossen für Modifikationen. Die einzelne Implementierung der obigen Methode muss nicht geändert werden, da neue Klassen definiert werden, die IObjectWithSpeed ​​implementieren. 

5
Andy Thomas

Eine Schnittstelle ist nicht einfach eine Methodensignatur.

Es ist ein Typ, der einen Vertrag darstellt. Der Vertrag ist die Sache, nicht die Methodensignaturen. Wenn eine Klasse eine Schnittstelle implementiert, liegt dies daran, dass es einen Vertrag für ein gemeinsames Verhalten gibt, an dem die Klasse ein Interesse an der Implementierung als Typ hat. Dieser Vertrag wird über die angegebenen Mitglieder ausgeführt, die in der Regel Methodenkörper sind, aber auch statische Endfelder enthalten können.

Es kann sein, dass ein Tiger und ein Flugzeug beide als ein Typ ausgedrückt werden können, dessen gemeinsames Verhalten durch speed () implementiert wird. Wenn dies der Fall ist, stellt die Schnittstelle den Vertrag dar, um dieses Verhalten auszudrücken.

3
scottb

Abgesehen davon, dass sie für die Funktionalität dieser Klassen beschreibend sind, können Methoden eines Interfaces auch ohne Wissen über die implementierenden Klassen verwendet werden, selbst für Klassen, die noch nicht definiert wurden.

Wenn Sie beispielsweise eine Klasse Transport benötigen, die beispielsweise effiziente Routen berechnet, kann dieser Klasse eine Klasse zugewiesen werden, die ClassWithSpeed als Parameter implementiert, und die Methode speed() für die Berechnung des benötigten Werts verwenden. Auf diese Weise können Sie es mit unserer Klasse Aeroplane verwenden, aber auch mit jeder Klasse, die wir später definieren, beispielsweise Boat. Java sorgt dafür, dass, wenn Sie eine Klasse als Parameter für Transport verwenden möchten, ClassWithSpeed implementiert wird und dass jede Klasse, die ClassWithSpeed implementiert, die Methode speed() implementiert, damit sie verwendet werden kann.

3
anana

Ich möchte auf viele theoretische Details eingehen, aber ich werde versuchen, es anhand dieses Beispiels zu erklären.

Betrachten Sie JDBC-API . Diese API dient zum Umgang mit datenbankbezogenen Optionen in Java. Nun gibt es so viele Datenbanken in der Branche. Wie würde man Treiber dafür schreiben? Nun, der schnelle und schmutzige Ansatz kann die eigene Implementierung mit eigenen Klassen und API sein.

Aber denken Sie aus der Perspektive des Programmierers. Werden sie anfangen, die API von DATABASE DRIVER zu lernen, während sie eine andere Datenbank verwenden? Die Antwort ist nein.

Was ist also die Lösung für das Problem? Habe nur eine gut definierte API, die jeder für seine eigene Implementierung erweitern kann.

In der JDBC-API gibt es einige Schnittstellen, die Connection, ResultSet, PreparedStatement, Statement usw. sind. Nun wird jeder Datenbankanbieter die Schnittstelle implementieren und seine eigene Implementierung dafür schreiben. Ergebnis : Reduzierter Aufwand des Entwicklers und leichte Verständlichkeit. 

Woraus könnte diese benutzerdefinierte Implementierung bestehen? Es ist einfach. Sie tun was, nehmen die ResultSet-Schnittstelle zum Beispiel und implementieren sie und in welcher Methode auch immer das ResultSet zurückgegeben wird, return THE CLASS THAT IMPLEMENTS ResultSet-Schnittstelle wie folgt

ResultSet rs = new ResultSetImpl (); // Dies ist, was sie intern tun.

Schnittstelle ist also wie Verträge. Sie definieren, was Ihre Klasse kann und geben Ihrer Anwendung Flexibilität. Sie können Ihre eigenen APIs mithilfe von Schnittstellen ordnungsgemäß erstellen.

Hoffe das hilft dir.

3
trapaank

Die Schnittstelle (als Sprachkonstrukt) wird vom Compiler verwendet, um zu beweisen, dass der Methodenaufruf gültig ist, und ermöglicht es Ihnen, abhängige Klassen mit der implementierenden Klasse zu interagieren, während sie möglichst wenig über die implementierende Klasse wissen.

1
Ryan Ransford

Auf der Ebene der Sprachen besteht die einzige Verwendung von Schnittstellen darin, wie Sie erwähnt haben, in der Lage zu sein, auf verschiedene Klassen auf eine gemeinsame Weise zu verweisen. Auf Menschenebene sieht das Bild jedoch anders aus: IMO Java ist stark, wenn es in großen Projekten verwendet wird, bei denen das Design und die Implementierung von separaten Personen, oft von separaten Unternehmen, durchgeführt werden. Anstatt eine Spezifikation in ein Word-Dokument zu schreiben, können die Systemarchitekten nun eine Reihe von Klassen erstellen, die Implementierer dann direkt in ihre IDEs einfügen und damit arbeiten können. Mit anderen Worten ist es bequemer, statt zu erklären, dass "Klasse X die Methoden Y und Z implementiert, damit sie für den Zweck A verwendet werden können, nur um zu sagen, dass" Klasse X die Schnittstelle A implementiert.

1
Bobby Marinoff

Haben Sie versucht, die Komposition stattdessen zu verwenden ?, wenn zwei unterschiedliche Klassen dieselben Fähigkeiten erben sollen wie eine Klasse, die ein Objekt des Typs übernimmt, mit dem es arbeitet, indem Sie abstrakte Klassen verwenden und die Instanzen prüfen. Schnittstellen sind nützlich, um das Einfügen von Methoden in die Klasse zu erzwingen, es ist jedoch keine Implementierung erforderlich, oder es sind zwei Codierteams erforderlich, um an verschiedenen Codierungsbereichen zu arbeiten.

Class Tiger {
  public MovingEntity mover;

 public Tiger(){

  mover.speed=30;
  mover.directionX=-1;
  mover.move(mover);

 }

}
Class Plane {
  public MovingEntity mover;

 public Plane(){
  mover.speed=500;
  mover.directionX=-1;
  mover.move(mover);

 }


Abstract Class Moverable(){
  private int xPos;
  private int yPos;
  private int directionX;
  private int directionY;
  private int speed;


Class MovingEntity extends Moverable {
 public void move(Moverable m){
   if(m instanceof Tiger){

      xPos+=directionX*speed;
      yPos+=directionY*speed;

   }else if(m instanceof Plane){
      xPos+=directionX*speed;
      yPos+=directionY*speed;

   }
 }
1
David Ryan

Dies ist eine sehr breite Frage, um eine einfache Antwort zu geben. Ich kann ein Buch Schnittstellenorientiertes Design empfehlen: Mit Mustern . Es erklärt alle Möglichkeiten von Schnittstellen. Und warum sollten wir sie nicht vermeiden.

1
Mikhail

Weil das Erstellen einer Schnittstelle zu Polymorphismus über alle diese Klassen hinweg führt, z. B. Tiger und Airplane.

Sie können eine (abstrakte oder konkrete) Klasse erweitern, wenn die Funktionalität der Basisklasse auch der Kern der Funktionalität Ihrer Kindklasse ist.

Sie verwenden Schnittstellen, wenn Sie Ihrer Klasse zusätzlich zu ihrer Kernfunktionalität eine erweiterte Funktionalität hinzufügen möchten. Wenn Sie also Schnittstellen verwenden, erhalten Sie Polymorphismus, auch wenn dies nicht die Kernfunktionalität Ihrer Klasse ist (weil Sie durch die Implementierung der Schnittstelle einen Vertrag abgeschlossen haben). Dies ist ein großer Vorteil, wenn Sie mit jeder Klasse eine speed () - Methode erstellen.

0