W języku takim jak C ++, który umożliwia wielokrotne dziedziczenie i nie ma interfejsów, klasy abstrakcyjne, w których wszystkie metody są abstrakcyjne, mogą służyć jako interfejsy. Nie pracowałem tak bardzo z C ++, ale sądzę, że wielokrotne dziedziczenie może powodować problemy, gdy istnieją metody o tej samej nazwie w klasach podstawowych.
W językach takich jak PHP i C # interfejsy umożliwiają osiągnięcie podobnego polimorfizmu, chociaż nie lubię nazywać go „dziedziczeniem”, ponieważ istnieje koncepcyjna różnica między dziedziczeniem klasy abstrakcyjnej a implementacją interfejsu. Interfejsy usuwają problem konfliktu, ponieważ same nie zapewniają implementacji.
Interfejs służy jako umowa ze światem zewnętrznym, podczas gdy klasa abstrakcyjna może zapewnić implementację, chociaż jeśli zostanie użyta do „sfałszowania” interfejsu, najprawdopodobniej nie.
Główna różnica koncepcyjna polega na tym, że gdy klasa dziedziczy inną klasę (abstrakcyjną lub nie), istnieje relacja „jest”, więc a Car
jest a Vehicle
i Dog
jest Animal
. W przypadku interfejsu liczy się to, co robi obiekt. Więc zarówno Car
i Dog
może, jak Move()
i konsument wie o tym, ponieważ wdrażają Movable
, ale Samochód zdecydowanie nie jest Dog
ani Animal
. I implementacja ruchu będzie inna (koła vs nogi), ale kod zużywający się nie obchodzi i nie powinien się przejmować. Interfejsy dotyczą raczej zużywającego się kodu, a nie implementacji.
Najważniejsze jest to, że jeśli masz interfejsy w swoim wybranym języku, używaj ich do rzeczy, dla których są. Jeśli nie (jak w C ++), możesz je sfałszować za pomocą czysto abstrakcyjnych klas.