Czy OOP i całkowicie unika się dziedziczenia implementacji?

Jako przykład wybiorę Javę, większość ludzi o tym wie, choć działał również każdy inny język OO.

Java, podobnie jak wiele innych języków, ma dziedziczenie interfejsu i dziedziczenie implementacji. Na przykład. klasa Java może dziedziczyć z innej, a każda metoda, która ma tam implementację (zakładając, że rodzic nie jest abstrakcyjny), również jest dziedziczona. Oznacza to, że interfejs jest dziedziczony, a implementacja tej metody również. Mogę go zastąpić, ale nie muszę. Jeśli go nie zastąpię, odziedziczyłem implementację.

Jednak moja klasa może także „dziedziczyć” (nie w kategoriach Java) tylko interfejs, bez implementacji. Właściwie interfejsy są tak nazywane w Javie, zapewniają dziedziczenie interfejsu, ale nie dziedziczą żadnej implementacji, ponieważ wszystkie metody interfejsu nie mają implementacji.

Teraz było toartykuł mówi, że lepiej dziedziczyć interfejsy niż implementacje, możesz go przeczytać (przynajmniej w pierwszej połowie pierwszej strony), to całkiem interesujące. Unika problemów takich jakdelikatny problem klasy bazowej. Jak dotąd ma to sens i wiele innych rzeczy, o których mowa w tym artykule, ma dla mnie sens.

To, co mnie niepokoi, to to, że dziedziczenie implementacji oznaczaponowne użycie kodu, jedna z najważniejszych właściwości języków OO. Teraz, jeśli Java nie miała klas (jak James Gosling, ojciec chrzestny Java, zgodnie z tym artykułem), rozwiązuje ona wszystkie problemy związane z dziedziczeniem implementacji, ale w jaki sposób można ponownie wykorzystać kod?

Na przykład. jeśli mam klasę, samochód i samochód mają metodę move (), co powoduje, że samochód się porusza. Teraz mogę podklasować samochód na inny rodzaj samochodów, czyli wszystkie samochody, ale wszystkie są specjalnymi wersjami samochodu. Niektóre mogą poruszać się w inny sposób, i tak muszą nadpisać ruch (), ale większość po prostu utrzyma odziedziczony ruch, ponieważ poruszają się tak samo, jak abstrakcyjny samochód macierzysty. Załóżmy teraz, że w Javie istnieją tylko interfejsy, tylko interfejsy mogą dziedziczyć od siebie, klasa może implementować interfejsy, ale wszystkie klasy są zawsze ostateczne, więc żadna klasa nie może dziedziczyć z żadnej innej klasy.

W jaki sposób uniknąłbyś tego, gdy masz samochód interfejsu i sto klas samochodów, które musisz zaimplementować dla każdej z nich identyczną metodą move ()? Jakie koncepcje ponownego wykorzystania kodu inne niż dziedziczenie implementacji istnieją w świecie OO?

Niektóre języki mają Mixins. Czy Mixins jest odpowiedzią na moje pytanie? Czytałem o nich, ale nie mogę sobie wyobrazić, jak Mixins działałyby w świecie Java i czy naprawdę potrafią rozwiązać problem tutaj.

Innym pomysłem było to, że istnieje klasa, która implementuje tylko interfejs Car, nazwijmy ją AbstractCar i implementuje metodę move (). Teraz inne samochody również implementują interfejs Car, wewnętrznie tworzą instancję AbstractCar i implementują własną metodę move (), wywołując move () na wewnętrznym abstrakcyjnym Car. Ale czy nie byłoby to marnowaniem zasobów na nic (metoda wywołująca po prostu inną metodę - okej, JIT mógłby wbudować kod, ale nadal) i używając dodatkowej pamięci do przechowywania wewnętrznych obiektów, nie potrzebowałbyś nawet dziedziczenia implementacyjnego? (w końcu każdy obiekt potrzebuje więcej pamięci niż tylko suma hermetyzowanych danych).

public void move() {
    abstractCarObject.move();
}

?

Każdy może sobie wyobrazić lepszy pomysł, jak uniknąć dziedziczenia implementacji i nadal móc w łatwy sposób wykorzystywać kod?

questionAnswers(8)

yourAnswerToTheQuestion