peter: Frage Interfaces

Hi ich habe eine Frage zu Interfaces und deren Verwendung im Code.
Wenn ich ein Interface habe:

  
public interface A {  
   public void do();  
}  

und eine Klasse welche das Implementiert

  
public void B implements A {  
   public void do() {  
      // implementierung von do  
   }  
   public void print(String s) {  
      System.out.println(s);  
   }  
}  

Wie arbeite ich jetzt damit?
A obj = new B();
oder
B obj = new B();

Ich weiß zwar im 1. Fall dass ich mitm Interface arbeiten kann und ich auf jeden fall die Methode do verwenden kann, aber ich könnte ja außer einem Cast auf B nicht auf print zugreifen. Das gleiche Problem hätte ich auch wenn meine Klasse B von einer abstrakten Klasse methoden erben würde. Das heißt ich müsste ja eigentlich immer mit der Implementierung arbeiten.

Das würde aber heißen dass ich im Code selbst immer die Implementierung verwende, und bei Funktionsaufrufen zwischen Klassen zb mit dem Interface arbeite.

Also Klasse B kommunziert mit einer anderen Klasse C und C benötigt aber nur die do funktion, egal welches Objekt reinkommt, dann würde ich zb das Objekt übergeben können oder?

bin mir nicht sicher ob ich das korrekt verstanden habe.

danke

  1. Hi ich habe eine Frage zu Interfaces und deren Verwendung im Code.
    Wenn ich ein Interface habe:

    public interface A {
       public void do();
    }

    
    > und eine Klasse welche das Implementiert  
    > ~~~java
      
    
    > public void B implements A {  
    >    public void do() {  
    >       // implementierung von do  
    >    }  
    >    public void print(String s) {  
    >       System.out.println(s);  
    >    }  
    > }  
    > 
    
    

    Wie arbeite ich jetzt damit?
    A obj = new B();
    oder
    B obj = new B();

    Ich weiß zwar im 1. Fall dass ich mitm Interface arbeiten kann und ich auf jeden fall die Methode do verwenden kann, aber ich könnte ja außer einem Cast auf B nicht auf print zugreifen.

    Richtig! Gut erkannt und gute Frage.
    Hier kommt es drauf an. In der Regel wirst du Dein B auch als B deklarieren wollen, aber nicht immer. Casten ist immer sehr schlecht und sollte unter allen Umständen vermieden werden. Sie sind ein Zeichen für schlechtes Design und sorgen unter anderem dafür, dass der Compiler nicht mehr zur Compilezeit mögliche Fehler entdecken kann.

    Wenn du also sowieso nur die Methoden des Interfaces brauchst, dann solltest du auch das Interface (also in deinem Beispiel A) für die Deklaration verwenden. Dies hat den Vorteil, dass du später einfach statt "new B()" ein andere Klasse mit "new C()" nutzen kannst und ansonsten _nichts_ am restlichen Code zu ändern brauchst. Brauchst du aber (irgendwann später) die Methoden der Klasse B, dann musst du diese wählen (um den fehleranfälligen Cast zu vermeiden). Dadurch kannst du aber später B nicht einfach durch C austauschen, sondern musst an allen Stellen gucken, wie B verwendet wird und dies entsprechend anpassen.

    Wenn man z.B. das Interface Animal und die Klasse Dog implements Animal hat, dann hängt es davon ab, ob du an der jeweiligen Stelle einfach irgendein Animal haben willst oder ob du einen Dog haben willst und auch dessen spezifische Methoden benötigst. Beispiel: wenn du irgendwo HolStöckchen() aufrufen willst, dann nimm Dog. Wirst du nur eat() und sleep() aufrufen (was jedes Animal kann), dann nimm Animal, sodass du später auch statt des Hundes eine Katze einsetzen kannst.

    1. Okay glaub ich habs.. Ich dachte mir nämlich auch bzgl. Getter und Setter bleibt ja eigentlich nur die Möglichkeit normal mit der Klasse zu arbeiten.

      D.h. wahrscheinlich dort wo ich direkt mit der Klasse arbeite, daten setze etc arbeite ich mit der Klasse selbst. Wenn ich dann zb zu einer Service-Schicht das objekt weiterreiche die dann was macht, wird dort mit dem Interface weitergearbeitet.

        
      B obj = new B();  
      b.do....  
      ..  
      ..  
      interface ServiceI {  
          public boolean checkIfNotNull(A obj);  
      }  
      ..  
      ..  
      ServiceI service = new MyService();  
      boolean result = service.checkIfNotNull(B);  
      ..  
      ..  
      class MyService implements ServiceI {  
         public boolean checkIfNotNull(A obj) {  
             return obj != null;  
         }  
      }  
      
      

      Das würde aber auch bedeuten alles was private ist, ist ja uninteressant, d.h. wenn eine service-implementierung zusätzlich private methoden zur berechnung etc verwendet, kann ich immer mit dem Interface arbeiten, da ich ja sowieso keinen zugriff habe. Interessant wäre das nur für zusätzliche public methoden?

      danke

  2. hi,

    Interface-Methoden sind immer public, weil: Sie werden nicht innerhalb einer Klasse verwendet sondern außerhalb der Klasse über die Instanz der Klasse aufgerufen.

    Eine Klassenerweiterung (Subklasse) die ein Interface verwendet, muss es implementieren, d.h., alle Methoden des IF müssen in der Subklasse selbst als public definiert sein.

    Also Klasse B kommunziert mit einer anderen Klasse C und C benötigt aber nur die do funktion, egal welches Objekt reinkommt, dann würde ich zb das Objekt übergeben können oder?

    Siehe oben: _Innerhalb_ einer Klasse werden Interface-Methoden nicht verwendet noch benötigt, sondern implementiert. In Deiner main werden Methoden eines Interface entweder über Instanz-B oder über Instanz-C aufgerufen.

    MfG