Jump to content
Unity Insider Forum

Interfaces, wann, wofür oder überhaupt benutzt? Eure Erfahrung


MaZy

Recommended Posts

Hallo,

 

ich sehe öfters, dass man von Interfaces spricht und sie anwendet. Die Idee dahinter, wie sie funktionieren gefällt mir, aber manchmal finde ich das bisschen aufwendiger.

Ich sehe öfters sowas wie IControlable, IDamageable. Zu mindest als Beispiel.

Jetzt frage ich mich, welches aufwendiger wäre. Eine Baseklasse zu haben, wo man erbt und vllt auch den Damage-Prozess falls das existiert und dann anpasst. Wenn man kein Damage will kann ja man beim overriden der Funktion return geben fertig.. dann ist es quasi deaktiviert.

 

Andersherum, wenn man IDamageable verwendet muss man doch jedes mal in die vorhanden Methoden anpassen.

Beispiel IControlable. Müsste jedes mal Coden, dass man das Objekt kontrollieren, bewegen kann oder so.

 

Verstehe leider noch nicht so den Sinn daran. Vielleicht habe ich auch leider doofe Beispiele rausgefunden ^^.

Link to comment
Share on other sites

Das kommt denke ich immer so drauf an..

Je nach Situation ist ein Interface die richtige Wahl, manchmal eine abstrakte Klasse und manchmal einfach nur eine Vererbung..

Ich hab Interfaces bisher eigentlich nur für Implementierungen des State Patterns benutzt, wobei die anderen beiden Möglichkeiten auch gar nicht erst in Frage kamen.

 

Aber du musst dich fragen wofür Interfaces eigentlich da sind.

Bist du alleine oder in einem kleinen Team und kennst jede Implementierung auswendig, wird sich das alles nicht viel nehmen und Interfaces sind dann auch nicht unbedingt das Nützlichste.. In vielen Fällen finde ich abstrakte Klassen dann handlicher.

 

Aber wenn man in einem großen Team arbeitet oder vllt sogar Teile des Projekts von einem anderen Team bekommt, (oder das Projekt an ein anderes Team übergeben werden soll) können Interfaces schon sehr wichtig sein.

Ein Interface soll ja nämlich auch gar keine Funktionalität bieten (kann es ja auch gar nicht - so ganz ohne Methodenrumpf), sondern einfach dafür sorgen, dass alles kompatibel ist und Code von mehreren Teams/Teammitglieder zusammen passt.

 

Ich würde IControlable und IDamageable für mich jetzt auch nicht implementieren..

Aber:

Vielleicht möchte ja jemand Plattformen haben, die sich je nach Typ unterschiedlich bewegen.. Dann bringt es ihm nichts wenn er eine abstrakte Klasse benutzt, dort eine Defaul Bewegung implementiert und für alle anderen Plattformtypen die Methoden überschreiben muss..

Da ist es vom Design her schöner wenn er ein Interface implementiert in dem jedes Objekt mittels einer speziellen Methode bewegt wird..

Aber wie oben schon gesagt.. Arbeitest nur du alleine dran, macht es quasi keinen Unterschied was du da benutzt..

Im Team sieht die Sache schon anders aus.

Denn es ist doch besser wenn jemand aus einem anderen Team eine neue Plattform erstellt und der Compiler sagt "Du musst die "Move()" Methode implementieren", statt dass er von einer abstrakten Klasse ableitet und sich dann wundert wieso sich seine Plattform bewegt (weil er die Methode nicht mit einem return überschrieben hat) und er nicht weiß warum.

 

@edit:

Mal ganz davon abgesehen, dass es vielleicht gar nicht möglich ist von einer abstrakten Klasse abzuleiten, wenn man bereits von einer anderen Klasse ableiten muss ^^

Interfaces kann man ja so viele implementieren wie man lustig ist.

Gut in Unity wird das wohl eher seltener der Fall sein, denn dann lässt man hald die abstrakte Klasse schon mal von MonoBehaviour ableiten und es schadet wahrscheinlich nicht weil alle Kindklassen ebenfalls MonoBehaviour sein sollen, aber wenn man sich außerhalb von Unity bewegt könnte das unter Umständen schnell zum Problem werden.

Link to comment
Share on other sites

Interfaces definieren nur eine gemeinsame Schnittstelle unabhängig von der tatsächlichen Implementierung. Wenn du eine Basisimplementierung anbieten möchtest da es klar ist dass diverse Properties oder Methoden einer Schnittstelle nur selten ein anderes verhalten als das von dir gewünschte Standardverhalten aufweisen sollen dann bietest du eine Basisklasse an die genau dies Implementiert.

 

Java bietet im neusten Standard sogar die Möglichkeit an Defaultimplementierungen direkt im Interface anzugeben.

 

Nun aber zu deiner Frage wieso es Interfaces gibt man aber auch direkt eine Basisklasse anbieten kann:

 

Nehme dir das bekannte IDisposable Interface vor, dies bietet nur eine Methode an: void Dispose() was wäre hier die Standardimplementierung? Es gibt keine, denn jeder Typ der IDisposable implementiert wird mit sehr hoher Wahrscheinlichkeit etwas anderes machen.

 

Aber wieso dann nicht einfach im konkreten Typ selbst eine Methode Free() Delete() oder Dispose() anbieten?

 

Ganz einfach, dadurch müsstest du jeden dieser Typen speziell berücksichtigen und behandeln was bei einem gemeinsamen Interface was diese Typen implementieren nicht der Fall wäre. Du könntest jedes Objekt was explizit freigegebenw erden muss in eine Liste von Typ List < IDisposable > legen und einfach über diese Liste iterieren udn Dispoise aufrufen. Der konkrete Typ der Element in dieser Liste ist dabei irrelevant, du musst nicht folgendes machen:

 

if (element is MyTypeA)
 (element as MyTapeA).Free();
else if (element is MyTypeB)
 (element as MyTapeB).Delete();
else if (element is IDisposable)
 (element as IDisposable).Dispose();

 

sondern kannst das hier schreiben:

 

element.Dispose();

 

Ein weiterer Grund für Interfaces ist dass du einfach alternative Implementierungen anbieten kannst, was zB beim Test Driven Development interessant wird bei dem du einfach Mockklassen anbieten kannst die so tun als wären sie eine valide Implementierun eines bestimmten Interfaces. Der Sinn darin ist dass du betsimmte Objekte testen kannst ohne die Abhängigkeit zu anderen Elementen deines Codes.

 

Hier ein Beispiel, sag du mir was besser zum testen ist:

 

void TestForMyClassC()
{
   var a = new MyClassA();
   var b = new MyClassB();
   var c = new MyClassC(a, ;

   Test.IsEqual(c.Foo, "Hallo Welt");
}

 

oder:

private class AMock : IMyInterfaceA
{
   public virtual void DoSomething() { /* nop */}
   public virtual void DoSomethingElse() { /* nop */}
}

private class BMock : IMyInterfaceB
{
   public virtual bool Bla() { return false; }
}

void TestForMyClassC()
{
   var a = new AMock();
   var b = new BMock();
   var c = new MyClassC(a, ;

   Test.IsEqual(c.Foo, "Hallo Welt");
}

 

In der ersten Variante Testest du auch MyClassA und MyClassB, auch wenns bei dem test gar nicht um die Abhängigkeiten geht sondern nur um MyClassC, dadurch dass man die beiden nötigen Abhängigen Interface mocken kann, bezieht sich der Test in der zweiten Variante wirklich nur auf MyClassC. Damit kann man natürlich Fehler viel einfacher finden und Komponenten besser wiederverwenden.

 

Ausserdem kann man nur einmal von einer Klasse ableiten, aber beliebig oft von Interfaces. (Danke an Taiwaz, den Punkt habe ich gar nicht weiter beachtet).

Link to comment
Share on other sites

Archived

This topic is now archived and is closed to further replies.

×
×
  • Create New...