Das wurde mir auch beigebracht und ich bevorzuge Schnittstellen, wo es möglich ist (natürlich verwende ich immer noch Vererbung, wo es Sinn macht).
Eine Sache, die ich denke, ist es, Ihren Code von bestimmten Implementierungen zu entkoppeln. Angenommen, ich habe eine Klasse namens ConsoleWriter, die an eine Methode übergeben wird, um etwas auszuschreiben, und die es in die Konsole schreibt. Nehmen wir nun an, ich möchte zum Drucken in ein GUI-Fenster wechseln. Nun muss ich entweder die Methode modifizieren oder eine neue schreiben, die GUIWriter als Parameter verwendet. Wenn ich mit der Definition einer IWriter-Schnittstelle begonnen hätte und die Methode einen IWriter einbeziehen würde, könnte ich mit dem ConsoleWriter (der die IWriter-Schnittstelle implementieren würde) beginnen und später eine neue Klasse namens GUIWriter (der auch die IWriter-Schnittstelle implementiert) und dann I schreiben müsste nur die Klasse ausschalten, die bestanden wird.
Eine andere Sache (die für C # zutrifft, bei Java ist sie nicht sicher) ist, dass Sie nur eine Klasse erweitern, aber viele Schnittstellen implementieren können. Nehmen wir an, ich hatte Klassen mit den Namen Teacher, MathTeacher und HistoryTeacher. Jetzt erweitern sich MathTeacher und HistoryTeacher von Teacher, aber was ist, wenn wir eine Klasse wollen, die jemanden repräsentiert, der sowohl MathTeacher als auch HistoryTeacher ist. Es kann ziemlich chaotisch werden, wenn Sie versuchen, von mehreren Klassen zu erben, wenn Sie es immer nur einzeln tun können (es gibt Möglichkeiten, aber sie sind nicht genau optimal). Mit Interfaces können Sie zwei Interfaces namens IMathTeacher und IHistoryTeacher haben und dann eine Klasse, die von Teacher ausgeht, und diese beiden Interfaces implementieren.
Ein Nachteil bei der Verwendung von Schnittstellen ist, dass manchmal Leute doppelten Code sehen (da Sie die Implementierung für jede Klasse erstellen müssen, um die Schnittstelle zu implementieren), aber es gibt eine saubere Lösung für dieses Problem, zum Beispiel die Verwendung von Dingen wie Delegaten (nicht sicher) was das Java-Äquivalent dazu ist).
Der Hauptgrund für die Verwendung von Schnittstellen gegenüber Vererbungen ist die Entkopplung des Implementierungscodes. Sie sollten jedoch nicht glauben, dass Vererbung böse ist, da sie immer noch sehr nützlich ist.