Podczas dzisiejszego przeglądu kodu mój kolega powiedział coś interesującego:
prototype
przydaje się tylko wtedy, gdy potrzebujesz dziedziczenia - a kiedy dziedziczenie jest zawsze dobrym pomysłem ?
Pomyślałem o tym i zdałem sobie sprawę, że zwykle używam dziedziczenia, aby obejść kod, który został źle zaprojektowany. Współczesny styl OO woli kompozycję niż dziedziczenie, ale nie znam żadnych języków, które wzięłyby to sobie do serca i faktycznie je egzekwowały .
Czy istnieją języki programowania ogólnego przeznaczenia z klasami, obiektami, metodami, interfejsami itp., Które nie pozwalają na dziedziczenie oparte na klasach? (Jeśli taki pomysł nie ma sensu, dlaczego nie?)
object-oriented
programming-languages
inheritance
Benjamin Hodgson
źródło
źródło
prototype
to również przydatne, gdy masz publiczne metody i właściwości, które powinny być współużytkowane między instancjami. Jest to także przydatne, ponieważ pozwala właściwie używaćinstanceof
operatora w JavaScript:if (foo instanceof Foo) { ...
.implements
słowa kluczowego i interfejsów (w przeciwieństwie do dziedziczenia stanu i zachowanie wprowadzone za pomocąextends
słowa kluczowego w klasach zawierających dowolną implementację).new
,this
Iprototype
są zbyt duże pole minowe do wspólnego użytku IMO.Odpowiedzi:
Pomijając kwestię definicji programowania obiektowego, pytanie staje się jednym z „czy istnieją języki, które używają wyłącznie kompozycji i nie mają narzędzi do dziedziczenia?”
Odpowiedź na to pytanie jest po prostu „tak”. W praktyce nie ma sposobu na dziedziczenie, o czym klasycznie się myśli. One mogą osadzony obiekt w innym obiekcie i przedłużyć ten obiekt. Z Object Desoriented Language ( mirror github ):
Masz strukturę osoby o nazwie, która jest łańcuchem. Ma funkcję publiczną o nazwie Intro, która zwraca nazwę. Struktura Woman ma również funkcję Intro, która ma dostęp do osadzonej w niej kolumny. I tak można spełnić zamiary dziedziczenia, używając tylko kompozycji.
Więcej na ten temat można znaleźć w Samouczkach GoLang: Dziedziczenie i podklasowanie w Go - lub jego zbliżonym podobieństwie .
Tak więc możliwe jest posiadanie języka OO bez dziedziczenia, a taki istnieje.
Wewnątrz go jest to nazywane osadzaniem i daje otaczającym strukturom możliwość dostępu do osadzonych pól i funkcji tak, jakby miały je również - ale nie jest to podklasa. Filozofię projektowania można znaleźć w Go FAQ: Dlaczego nie ma dziedziczenia typu?
źródło
typedef
iwstruct
C ...Odczytuje to bardzo podobnie do opisu VBA - Visual Basic for Applications, osadzonego w Microsoft Office i innych hostach obsługujących VBA (np. AutoCAD, Sage 300 ERP itp.), A nawet VB6. „A” „Basic” i tak oznacza „Uniwersalny”, więc jest część „ogólnego przeznaczenia”.
VB6 / VBA ma klasy (a zatem obiekty), metody i interfejsy - możesz zdefiniować
ISomething
interfejs w module klasy takim jak ten:A potem mają inną klasę, która to robi:
Do takiej klasy, nie ujawniającej żadnych członków publicznych, można było kiedykolwiek uzyskać dostęp tylko poprzez jej
ISomething
interfejs - i może istnieć dziesiątki różnych implementacjiISomething
, więc kod OOP VBA jest doskonale zdolny do polimorfizmu i jest całkowicie legalny dla danej klasy do implementacji wielu interfejsów.VB6 / VBA nie pozwala jednak na dziedziczenie klas , więc nie można dziedziczyć implementacji z innego typu, tylko z interfejsu. Niezależnie od tego, czy jest to wypadek, wada projektowa, genialny pomysł, czy ogromny brzydki nadzór, jest przedmiotem dyskusji; nie jest jasne, czy VB6 / VBA bierze to sobie do serca , ale zdecydowanie to egzekwuje .
Jeśli Go nie wykonuje dziedziczenia klas i mimo to jest językiem OOP , to nie rozumiem, dlaczego VB6 / VBA nie może być również uważany za język OOP.
</PreemptiveResponseToVBAHatersThatWillSayItIsNotAnOOPLanguage>
źródło
Możesz zmusić kompilator do egzekwowania dziedziczenia selektywnego poprzez zastosowanie prywatnych / chronionych i poprzez nowoczesne wykorzystanie technik „PImpl” lub „Private Implementation”.
Wiele interfejsów API udostępnia tylko te komponenty, które użytkownik chciałby odziedziczyć, a resztę ukrywa w osobnej klasie implementacji. Można więc pisać klasy, których publiczne interfejsy są w rzeczywistości nie do odziedziczenia, możliwe do użycia tylko poprzez kompozycję obiektów i wymuszone przez kompilator. Jest to często dobra praktyka, gdy używa kompilatora do wymuszania zamiarów oprogramowania.
Szybkie wyszukiwanie funkcji prywatnych członków w javascript pokazuje, że istnieje podobna zasada, chociaż każdy może zobaczyć twój kod, jeśli może go użyć: http://www.crockford.com/javascript/private.html
źródło