Dlaczego frameworki Windows Forms / Swing preferują dziedziczenie zamiast kompozycji?

12

Dzisiaj mój profesor skomentował, że to dziwne, że chociaż filozofia SWT polega na tworzeniu własnych kontroli przez kompozycję, Swing wydaje się faworyzować dziedziczenie.

Prawie nie mam kontaktu z obiema platformami, ale z tego, co pamiętam w Windows Forms C #, zwykle rozszerza się sterowanie, podobnie jak Swing.

Ponieważ ludzie zazwyczaj wolą kompozycję niż dziedziczenie, dlaczego ludzie z Swing / Windows Forms nie preferowali kompozycji zamiast dziedziczenia?

pochłonęło elysium
źródło
2
Wiele się zmieniło w ciągu 15-20 lat, te interfejsy API już istnieją! Silniki renderujące nie miały magicznego kleju XML do wiązania obiektów ekranowych z instancjami dowolnej konkretnej klasy „z powrotem w ciągu dnia”;)
1
Widzę większość kodu Swing używa rozszerzenia według składu. Nie jestem pewien, skąd twój profesor zbiera jego dane.
Sam widziałem dużo huśtania się w sieci z dziedziczeniem zamiast kompozycji - głównie tutoriale. ale formularze systemu Windows są tak naprawdę używane prawie wyłącznie na podstawie dziedziczenia!
pożarł elysium

Odpowiedzi:

7

JComponentujawnia wiele funkcjonalności . Gdyby JComponentbył interfejs i komponenty zostały zaimplementowane z kompozycją, proste komponenty musiałyby mieć dziesiątki prostych metod pakowania, np

class MyComponent implements JComponent {
    JPanel panel;
    public boolean contains(int x, int y) {
        return panel.contains(x, y);
    }
    ...
}

Istnieje również powód wydajności, aby preferować dziedziczenie nad kompozycją - przesłonięcie nic nie kosztuje (zakładając brak superwywołania), a kompozycja kosztuje dodatkowo INVOKEVIRTUAL. Nie wiem, czy wpłynęło to na projekt Swinga, ale jest to duży problem dla klas kolekcji.

Daniel Lubarov
źródło
2

Swing Framework jest w rzeczywistości zaprojektowany zgodnie z Composite Design Pattern. Przyznaję, że jest tam wiele dziedziczenia, ale zwykle komponowałbyś własne formy przy użyciu kompozycji. Oznacza to, że forma jest kompozycją pojemników i kontroli poziomu pośredniego.

Vincent Ramdhanie
źródło
„To znaczy, że forma jest kompozycją pojemników i kontroli na poziomie pośrednim”. Pewnie. Ale zwykle widzę, że kiedy ludzie chcą stworzyć własne okno (lub jakkolwiek to się nazywa w Swing), odziedziczą po klasie okna zamiast używać kompozycji.
pożarł elysium
@devoured elysium To prawda. Ale aby stworzyć formę, użyliby kompozycji. Jest to więc trochę dziedzictwa i dużo kompozycji.
@devoured, myślę, że to przypadek ludzi, którzy nie zdają sobie sprawy, że samouczek, którego używają, nie jest zgodny z najlepszymi praktykami, ponieważ sprzyja zwięzłości.
Peter Taylor
1

W Javie dużo łatwiej jest korzystać z dziedziczenia tylko dlatego, że wszystko jest wirtualne. Chcesz naprawić „funkcję” w JTable / JFrame? Rozszerz go, zastąp metody problematyczne, a następnie użyj wszędzie tabeli / ramki.

Myślę o takich rzeczach jak WPF, gdzie powiązanie danych jest podstawową cechą projektu, znacznie ułatwia tworzenie kompozycji zamiast dziedziczenia.

John Gardner
źródło
Co masz na myśli mówiąc „wszystko jest wirtualne ”?
Jonas
w java każda metoda jest domyślnie wirtualna (może zostać zastąpiona). W języku C # musisz jawnie zadeklarować metodę jako virtual, i aby ją zastąpić, jawnie zadeklaruj ją jako override. W Javie można zastąpić nic widać i można zwiększyć swoją widoczność w podklasie (można dokonać metodami chronione publicznego w podklasie!)
John Gardner
Pamiętaj, że nie można przesłonić finalmetody w Javie, nawet jeśli sama klasa podstawowa nie jest final.
perp.
to prawda @perp. ale w java musisz zejść z drogi (dodając końcowy), aby zapobiec wirtualnemu. C # to odwrotna droga, musisz zrobić wszystko, aby być wirtualnym. Bardzo niewielki procent standardowego środowiska wykonawczego Java jest oznaczony jako końcowy.
John Gardner,
1

W Effective Java , pozycja 17, Bloch wspomina, że ​​klasa zaprojektowana do dziedziczenia „musi udokumentować swoje samodzielne stosowanie nadrzędnych metod”. Znakiem rozpoznawczym tego jest zwrot „ implementacja” . Zobaczysz to w klasach takich jak JTablei JInternalFrame. Jest to jedna miara dziedziczenia według projektu w Swing.

trashgod
źródło
-2

Od C # 3.5 mamy pojęcie nazywane jako Metody Rozszerzenia, które pozwalają na pojęcie składu niż dziedziczenia.

W tym procesie implementujemy rozszerzoną funkcjonalność do istniejącej klasy poprzez dodanie klasy rozszerzającej, która renderuje nową funkcję do istniejącej klasy.

Więcej informacji można znaleźć tutaj

Saravanan
źródło
Nie widzę związku z tworzeniem nowych klas Kontroli WinForm. Czy mógłbyś opracować?
Peter Taylor
@Peter: Nie dotyczy to tylko klas formularzy systemu Windows. Może to dotyczyć również naszego kodu. Możesz rozszerzyć dowolną z istniejących klas, po prostu dodając klasę statyczną, a następnie dodając nową metodę z 1. argumentem w ten sposób, aby można było połączyć obiekt podstawowy. Po skompilowaniu kodu otrzymujesz nowo dodaną metodę jako metodę samej klasy podstawowej. Tak stwierdza kompozycja. mam nadzieję, że mam rację ..
Saravanan
1
Wiem, jakie są metody rozszerzania i czasami są bardzo przydatne, ale to pytanie dotyczy różnych podejść do tworzenia nowych klas.
Peter Taylor
@Peter: W takim razie mogę jedynie wskazać użycie częściowych klas, poza tym, że według mnie C # nie ma żadnej innej niezwykłej funkcji. Jeśli znasz jakieś, daj mi znać.
Saravanan