Programowanie obiektowe - Object-oriented programming

Z Wikipedii, wolnej encyklopedii

Przedmiotem zorientowane programowania ( OOP ) jest paradygmat programowania oparty na koncepcji „ obiektów ”, która może zawierać dane i kod pocztowy: dane w postaci pola (często zwane cechy lub właściwości ), a kod w postaci procedur (często nazywane metodami ).

Cechą obiektów jest to, że własne procedury obiektu mogą uzyskiwać dostęp do samych pól danych i często je modyfikować (obiekty mają pojęcie this lub self ). W OOP programy komputerowe są projektowane poprzez tworzenie ich z obiektów, które oddziałują na siebie. Języki OOP są różnorodne, ale najpopularniejsze są oparte na klasach , co oznacza, że ​​obiekty są instancjami klas , które również określają ich typy .

Wiele z najczęściej używanych języków programowania (takich jak C ++, Java, Python, etc.) są multi-paradygmat i wspierać ich programowania obiektowego w większym lub mniejszym stopniu, zwykle w połączeniu z imperatywu , programowanie proceduralne . Istotne języki obiektowe to: (kolejność na liście na podstawie indeksu TIOBE ) Java , C ++ , C # , Python , R , PHP , Visual Basic.NET , JavaScript , Ruby , Perl , Object Pascal , Objective-C , Dart , Swift , Scala , Kotlin , Common Lisp , MATLAB i Smalltalk .

funkcje

Programowanie zorientowane obiektowo wykorzystuje obiekty, ale nie wszystkie powiązane techniki i struktury są obsługiwane bezpośrednio w językach, które twierdzą, że obsługują OOP. Funkcje wymienione poniżej są powszechne w językach uważanych za silnie zorientowane na klasy i obiektowe (lub wieloparadygmat z obsługą OOP), z wymienionymi znaczącymi wyjątkami.

Udostępniane w językach innych niż OOP

Obsługa programowania modułowego zapewnia możliwość grupowania procedur w pliki i moduły do ​​celów organizacyjnych. Moduły mają przestrzenie nazw, więc identyfikatory w jednym module nie będą kolidować z procedurą lub zmienną o tej samej nazwie w innym pliku lub module.

Obiekty i klasy

Języki obsługujące programowanie obiektowe (OOP) zazwyczaj używają dziedziczenia do ponownego wykorzystania kodu i rozszerzalności w postaci klas lub prototypów . Te, które używają klas, obsługują dwie główne koncepcje:

  • Klasy - definicje formatu danych i dostępnych procedur dla danego typu lub klasy obiektu; mogą również zawierać same dane i procedury (znane jako metody klas), tj. klasy zawierają elementy składowe danych i funkcje składowe
  • Obiekty - instancje klas

Przedmioty czasami odpowiadają rzeczom znalezionym w prawdziwym świecie. Na przykład program graficzny może mieć takie obiekty, jak „okrąg”, „kwadrat”, „menu”. System zakupów online może zawierać takie obiekty, jak „koszyk”, „klient” i „produkt”. Czasami obiekty reprezentują bardziej abstrakcyjne jednostki, takie jak obiekt, który reprezentuje otwarty plik lub obiekt, który zapewnia usługę tłumaczenia pomiarów ze zwyczajowych w USA na metryczne.

Programowanie zorientowane obiektowo to coś więcej niż tylko klasy i obiekty; to cały paradygmat programowania oparty na [ sic ] obiektach (strukturach danych), które zawierają pola danych i metody. Ważne jest, aby to zrozumieć; używanie klas do organizowania razem zestawu niepowiązanych metod nie jest orientacją obiektową.

Junade Ali, opanowanie wzorców projektowych PHP

O każdym obiekcie mówi się, że jest instancją określonej klasy (na przykład obiekt z polem nazwy ustawionym na „Mary” może być instancją klasy Pracownik). Procedury w programowaniu obiektowym nazywane są metodami ; zmienne są również znane jako pola , elementy członkowskie, atrybuty lub właściwości. Prowadzi to do następujących warunków:

  • Zmienne klasowe - należą do klasy jako całości ; istnieje tylko jedna kopia każdego z nich
  • Zmienne lub atrybuty instancji - dane należące do poszczególnych obiektów ; każdy obiekt ma swoją własną kopię każdego z nich
  • Zmienne składowe - odnoszą się zarówno do zmiennych klasy, jak i instancji, które są zdefiniowane przez określoną klasę
  • Metody klasowe - należą do klasy jako całości i mają dostęp tylko do zmiennych klasy i danych wejściowych z wywołania procedury
  • Metody instancji - należą do poszczególnych obiektów i mają dostęp do zmiennych instancji dla określonego obiektu, do którego są wywoływane, danych wejściowych i zmiennych klas

Dostęp do obiektów jest nieco podobny do zmiennych o złożonej strukturze wewnętrznej, aw wielu językach są one faktycznie wskaźnikami , służącymi jako rzeczywiste odniesienia do pojedynczego wystąpienia wspomnianego obiektu w pamięci w stercie lub stosie. Zapewniają warstwę abstrakcji, której można użyć do oddzielenia kodu wewnętrznego od zewnętrznego. Kod zewnętrzny może używać obiektu, wywołując określoną metodę wystąpienia z określonym zestawem parametrów wejściowych, odczytując zmienną wystąpienia lub zapisując do zmiennej wystąpienia. Obiekty są tworzone przez wywołanie specjalnego typu metody w klasie zwanej konstruktorem . Program może tworzyć wiele instancji tej samej klasy, które są uruchamiane, które działają niezależnie. Jest to łatwy sposób wykorzystania tych samych procedur na różnych zestawach danych.

Programowanie zorientowane obiektowo, które używa klas, jest czasami nazywane programowaniem opartym na klasach , podczas gdy programowanie oparte na prototypach zazwyczaj nie używa klas. W rezultacie do definiowania pojęć obiektu i instancji używa się znacząco innej, choć analogicznej terminologii .

W niektórych językach klasy i obiekty można komponować przy użyciu innych pojęć, takich jak cechy i mieszanki .

Oparte na klasach a oparte na prototypach

W językach opartych na klasach klasy są wcześniej definiowane, a obiekty są tworzone na podstawie klas. Jeśli dwa obiekty, jabłko i pomarańcza, są tworzone z klasy Owoce , są one z natury owocami i gwarantuje się, że możesz obchodzić się z nimi w ten sam sposób; np programator można spodziewać się istnienia tych samych cech, takich jak kolor lub sugar_content lub is_ripe .

W językach prototypowych opartych na obiekty są podmioty podstawowej. Nie istnieją nawet żadne zajęcia . Prototyp obiektu jest po prostu inny obiekt, do którego obiekt jest powiązany. Każdy obiekt ma jedno łącze prototypowe (i tylko jedno). Nowe obiekty mogą być tworzone na podstawie już istniejących obiektów wybranych jako ich prototyp. Możesz zadzwonić dwa różne obiekty jabłko i pomarańczę owocu, jeśli obiekt owoc istnieje, a zarówno jabłko i pomarańcza mieć owoce jako prototyp. Idea klasy owoców nie istnieje jawnie, ale jako klasa równoważności obiektów posiadających ten sam prototyp. Atrybuty i metody prototypu delegowane do wszystkich obiektów klasy równoważności zdefiniowanej przez ten prototyp. Atrybuty i metody, których właścicielem jest dany obiekt, nie mogą być współużytkowane przez inne obiekty tej samej klasy równoważności; np. atrybut sugar_content może nieoczekiwanie nie występować w jabłku . W prototypie można zaimplementować tylko jedno dziedziczenie .

Dynamiczne wysyłanie / przekazywanie wiadomości

Obowiązkiem obiektu, a nie kodu zewnętrznego, jest wybranie kodu proceduralnego do wykonania w odpowiedzi na wywołanie metody, zazwyczaj poprzez wyszukanie metody w czasie wykonywania w tabeli skojarzonej z obiektem. Ta funkcja jest znana jako dynamiczne wysyłanie i odróżnia obiekt od abstrakcyjnego typu danych (lub modułu), który ma stałą (statyczną) implementację operacji dla wszystkich instancji. Jeśli zmienność wywołania zależy od więcej niż jednego typu obiektu, na którym jest wywoływana (tj. Co najmniej jeden inny obiekt parametr jest zaangażowany w wybór metody), mówi się o wysyłaniu wielokrotnym .

Wywołanie metody jest również znane jako przekazywanie wiadomości . Jest rozumiany jako komunikat (nazwa metody i jej parametry wejściowe) przekazywany do obiektu w celu wysłania.

Kapsułkowanie

Hermetyzacja to zorientowana obiektowo koncepcja programowania, która wiąże ze sobą dane i funkcje, które manipulują danymi, i która chroni zarówno przed zewnętrznymi zakłóceniami, jak i niewłaściwym wykorzystaniem. Hermetyzacja danych doprowadziła do powstania ważnej koncepcji OOP, polegającej na ukrywaniu danych .

Jeśli klasa nie zezwala na wywołanie kodu w celu uzyskania dostępu do wewnętrznych danych obiektu i zezwala na dostęp tylko za pomocą metod, jest to silna forma abstrakcji lub ukrywania informacji, znana jako hermetyzacja . Niektóre języki (na przykład Java) pozwalają klasom jawnie wymuszać ograniczenia dostępu, na przykład oznaczając dane wewnętrzne za pomocą private słowa kluczowego i wyznaczając metody przeznaczone do użycia przez kod poza klasą za pomocą public słowa kluczowego. Metody mogą być również zaprojektowane na poziomie publicznym, prywatnym lub pośrednim, takim jak protected (który umożliwia dostęp z tej samej klasy i jej podklas, ale nie obiektów z innej klasy). W innych językach (takich jak Python) jest to wymuszone tylko przez konwencję (na przykład private metody mogą mieć nazwy zaczynające się od podkreślenia ). Hermetyzacja zapobiega zajmowaniu się zewnętrznym kodem wewnętrznym działaniem obiektu. Ułatwia to refaktoryzację kodu , na przykład umożliwiając autorowi klasy zmianę sposobu, w jaki obiekty tej klasy reprezentują swoje dane wewnętrznie bez zmiany kodu zewnętrznego (o ile wywołania metod „public” działają w ten sam sposób). Zachęca również programistów do umieszczania całego kodu związanego z określonym zestawem danych w tej samej klasie, co organizuje go w celu łatwego zrozumienia przez innych programistów. Hermetyzacja to technika, która zachęca do oddzielenia .

Skład, dziedziczenie i delegowanie

Obiekty mogą zawierać inne obiekty w swoich zmiennych instancji; jest to znane jako kompozycja obiektu . Na przykład obiekt w klasie Employee może zawierać (bezpośrednio lub przez wskaźnik) obiekt z klasy Address, oprócz własnych zmiennych instancji, takich jak „first_name” i „position”. Kompozycja obiektu jest używana do reprezentowania relacji „ma-a”: każdy pracownik ma adres, więc każdy obiekt pracownika ma dostęp do miejsca, w którym można przechowywać obiekt Adres (bezpośrednio osadzony w sobie lub w oddzielnej lokalizacji adresowanej za pomocą wskaźnika) .

Języki obsługujące klasy prawie zawsze obsługują dziedziczenie . Umożliwia to układanie klas w hierarchię reprezentującą relacje typu „jest typu”. Na przykład klasa Pracownik może dziedziczyć po klasie Osoba. Wszystkie dane i metody dostępne dla klasy nadrzędnej pojawiają się również w klasie podrzędnej o tych samych nazwach. Na przykład klasa Person może definiować zmienne „first_name” i „last_name” za pomocą metody „make_full_name ()”. Będą one również dostępne w klasie Pracownik, do której można dodać zmienne „stanowisko” i „wynagrodzenie”. Technika ta umożliwia łatwe ponowne użycie tych samych procedur i definicji danych, a także potencjalnie odzwierciedla relacje w świecie rzeczywistym w intuicyjny sposób. Zamiast korzystać z tabel bazy danych i podprogramów programistycznych, programista wykorzystuje obiekty, które użytkownik może lepiej znać: obiekty ze swojej domeny aplikacji.

Podklasy mogą przesłonić metody zdefiniowane przez nadklasy. Dziedziczenie wielokrotne jest dozwolone w niektórych językach, ale może to skomplikować rozwiązywanie nadpisań. Niektóre języki mają specjalne wsparcie dla mieszanek , chociaż w każdym języku z dziedziczeniem wielokrotnym, mieszanka jest po prostu klasą, która nie reprezentuje relacji typu jest. Miksery są zwykle używane do dodawania tych samych metod do wielu klas. Na przykład klasa UnicodeConversionMixin może udostępniać metodę unicode_to_ascii (), jeśli jest zawarta w klasie FileReader i klasie WebPageScraper, które nie mają wspólnego elementu nadrzędnego.

Klas abstrakcyjnych nie można utworzyć w obiektach; istnieją tylko w celu dziedziczenia do innych „konkretnych” klas, które mogą zostać utworzone. W Javie final słowo kluczowe może służyć do zapobiegania podklasom klasy.

Doktryna składu nad dziedziczeniem opowiada się za wdrażaniem relacji ma-a przy użyciu kompozycji zamiast dziedziczenia. Na przykład, zamiast dziedziczyć po klasie Person, klasa Employee może nadać każdemu obiektowi Employee wewnętrzny obiekt Person, który następnie ma możliwość ukrycia przed zewnętrznym kodem, nawet jeśli klasa Person ma wiele publicznych atrybutów lub metod. Niektóre języki, takie jak Go, w ogóle nie obsługują dziedziczenia.

Zasada „ otwarte / zamknięte ” głosi, że klasy i funkcje „powinny być otwarte na rozszerzenie, ale zamknięte na modyfikacje”.

Delegowanie to kolejna funkcja językowa, której można używać jako alternatywy dla dziedziczenia.

Wielopostaciowość

Subtyping - forma polimorfizmu - ma miejsce, gdy wywołanie kodu może być agnostyczne co do klasy w obsługiwanej hierarchii, na której działa - klasy nadrzędnej lub jednego z jej potomków. Tymczasem ta sama nazwa operacji wśród obiektów w hierarchii dziedziczenia może zachowywać się inaczej.

Na przykład obiekty typu Circle i Square pochodzą ze wspólnej klasy o nazwie Shape. Funkcja Draw dla każdego typu Shape implementuje to, co jest konieczne do samodzielnego rysowania, podczas gdy wywołanie kodu może pozostać obojętne na konkretny typ rysowanego Shape.

Jest to inny rodzaj abstrakcji, który upraszcza kod poza hierarchią klas i umożliwia silne oddzielenie problemów .

Otwórz rekursję

W językach obsługujących otwartą rekurencję metody obiektów mogą wywoływać inne metody na tym samym obiekcie (w tym siebie), zwykle przy użyciu specjalnej zmiennej lub słowa kluczowego o nazwie this lub self . Ta zmienna jest późno wiązana ; umożliwia metodzie zdefiniowanej w jednej klasie wywołanie innej metody, która jest zdefiniowana później, w jakiejś jej podklasie.

Historia

Notacja UML dla klasy. Ta klasa Button zawiera zmienne dla danych i funkcji . Poprzez dziedziczenie można utworzyć podklasę jako podzbiór klasy Button. Obiekty są instancjami klasy.

Terminologia odwołująca się do „obiektów” i „zorientowanych” we współczesnym rozumieniu programowania obiektowego pojawiła się po raz pierwszy na MIT pod koniec lat pięćdziesiątych i na początku sześćdziesiątych. W środowisku grupy sztucznej inteligencji już w 1960 r. „Obiekt” mógł odnosić się do zidentyfikowanych obiektów ( atomy LISP ) posiadających właściwości (atrybuty); Alan Kay później przytoczył szczegółowe zrozumienie wewnętrznych cech LISP jako silny wpływ na jego myślenie w 1966 roku.

Pomyślałem o obiektach, które są jak komórki biologiczne i / lub pojedyncze komputery w sieci, zdolne do komunikowania się tylko z wiadomościami (więc wiadomości pojawiły się na samym początku - zajęło trochę czasu, aby zobaczyć, jak robić wiadomości w języku programowania na tyle wydajnie, aby być przydatny).

Alan Kay,

Innym wczesnym przykładem MIT był Sketchpad stworzony przez Ivana Sutherlanda w latach 1960–61; W glosariuszu raportu technicznego z 1963 roku opartego na swojej dysertacji o Sketchpadzie, Sutherland zdefiniował pojęcia „obiektu” i „instancji” (z pojęciem klasy objętym terminem „wzorzec” lub „definicja”), aczkolwiek wyspecjalizował się w interakcji graficznej. Ponadto wersja MIT ALGOL , AED-0, ustanowiła bezpośrednie połączenie między strukturami danych („plexami” w tym dialekcie) a procedurami, wstępnie konfigurując to, co później nazwano „komunikatami”, „metodami” i „funkcjami składowymi”.

W 1962 roku Kristen Nygaard zainicjował projekt języka symulacji w Norweskim Centrum Obliczeniowym , oparty na wcześniejszym wykorzystaniu symulacji Monte Carlo i jego pracy nad konceptualizacją systemów świata rzeczywistego. Ole-Johan Dahl oficjalnie dołączył do projektu, a język programowania Simula został zaprojektowany do działania na uniwersalnym komputerze automatycznym (UNIVAC) 1107. Simula przedstawił ważne koncepcje, które są dziś istotną częścią programowania obiektowego, takie jak dziedziczenie klas i obiektów i dynamiczne wiązanie . Simula została również zaprojektowana z myślą o programowaniu i bezpieczeństwie danych . Ze względów bezpieczeństwa zaimplementowano proces detekcji, dzięki któremu poprzez odniesienie liczy się ostatnia deska ratunku, usuwając nieużywane obiekty z pamięci o dostępie swobodnym (RAM). Ale chociaż idea obiektów danych zostały już ustalone przez 1965, enkapsulacji danych poprzez poziomy zakresu dla zmiennych , takich jak prywatny (-) i publicznego (+), nie zostały wdrożone w Simuli ponieważ byłoby to wymagane procedury dostępem być również ukryty.

We wczesnych etapach Simula miał być pakietem procedur dla języka programowania ALGOL 60. Niezadowoleni z ograniczeń narzuconych przez ALGOL naukowcy postanowili rozwinąć Simula w pełnoprawny język programowania, który wykorzystywał kompilator UNIVAC ALGOL 60. Simula była promowana przez Dahla i Nygaarda w latach 1965 i 1966, co doprowadziło do coraz większego wykorzystania języka programowania w Szwecji, Niemczech i Związku Radzieckim . W 1968 roku język stał się szeroko dostępny na komputerach Burroughs B5500 , a później został również zaimplementowany na komputerze URAL-16 . W 1966 roku Dahl i Nygaard napisali kompilator Simuli . Zaczęli zajmować się praktycznym wprowadzeniem w życie koncepcji klas rekordów Tony'ego Hoare'a , która została zaimplementowana w swobodnym, podobnym do angielskiego, uniwersalnym języku symulacji SIMSCRIPT . Zdecydowali się na uogólnioną koncepcję procesu z właściwościami klas rekordów i drugą warstwą przedrostków. Poprzez prefiksowanie proces może odwoływać się do swojego poprzednika i mieć dodatkowe właściwości. Simula wprowadziła w ten sposób hierarchię klas i podklas oraz możliwość generowania obiektów z tych klas.

Kompilator Simula 67 został uruchomiony dla komputerów mainframe IBM System / 360 i System / 370 w 1972 roku. W tym samym roku kompilator Simula 67 został uruchomiony bezpłatnie dla francuskich komputerów mainframe CII 10070 i CII Iris 80 . Do 1974 roku Stowarzyszenie Użytkowników Simuli miało członków w 23 różnych krajach. Na początku 1975 roku udostępniono bezpłatnie kompilator Simula 67 dla rodziny komputerów mainframe DECsystem-10 . Do sierpnia tego samego roku kompilator DECsystem-10 Simula 67 został zainstalowany w 28 lokalizacjach, z czego 22 w Ameryce Północnej. Zorientowany obiektowo język programowania Simula był używany głównie przez naukowców zajmujących się modelowaniem fizycznym , takim jak modele do badania i ulepszania ruchu statków i ich zawartości przez porty towarowe.

W latach siedemdziesiątych pierwsza wersja języka programowania Smalltalk została opracowana w Xerox PARC przez Alana Kaya , Dana Ingallsa i Adele Goldberg . Smaltalk-72 zawierał środowisko programistyczne i był dynamicznie wpisywany i początkowo był interpretowany , a nie kompilowany . Smalltalk zyskał uznanie dzięki zastosowaniu orientacji obiektowej na poziomie języka oraz graficznym środowisku programistycznym. Smalltalk przeszedł przez różne wersje i wzrosło zainteresowanie językiem. Chociaż Smalltalk był pod wpływem pomysłów wprowadzonych w Simuli 67, został on zaprojektowany jako w pełni dynamiczny system, w którym klasy mogą być tworzone i dynamicznie modyfikowane.

W latach siedemdziesiątych Smalltalk wpłynął na społeczność Lisp, aby włączyła techniki obiektowe, które zostały wprowadzone do programistów za pośrednictwem maszyny Lisp . Eksperymenty z różnymi rozszerzeniami Lispa (takimi jak LOOPS i Flavours wprowadzające wielokrotne dziedziczenie i mieszanki ) ostatecznie doprowadziły do Common Lisp Object System , który integruje programowanie funkcjonalne i programowanie obiektowe oraz umożliwia rozszerzenie za pomocą protokołu meta-obiektowego . W latach osiemdziesiątych podjęto kilka prób zaprojektowania architektur procesorów, które obejmowałyby sprzętową obsługę obiektów w pamięci, ale nie zakończyły się one sukcesem. Przykłady obejmują Intel iAPX 432 i Linn Smart Rekursiv .

W 1981 roku Goldberg redagował sierpniowe wydanie Byte Magazine , przedstawiając szerszemu gronu odbiorców Smalltalk i programowanie obiektowe. W 1986 roku Association for Computing Machinery zorganizowało pierwszą konferencję na temat programowania obiektowego, systemów, języków i aplikacji (OOPSLA), w której nieoczekiwanie uczestniczyło 1000 osób. W połowie lat 80-tych Objective-C został opracowany przez Brada Coxa , który używał Smalltalk w ITT Inc. , oraz Bjarne Stroustrup , który używał Simuli w swojej pracy doktorskiej, ostatecznie postanowił stworzyć obiektowy C ++ . W 1985 roku Bertrand Meyer wyprodukował również pierwszy projekt języka Eiffla . Koncentrując się na jakości oprogramowania, Eiffel jest czysto obiektowym językiem programowania i notacją obsługującą cały cykl życia oprogramowania. Meyer opisał metodę rozwoju oprogramowania Eiffla, opartą na niewielkiej liczbie kluczowych pomysłów z inżynierii oprogramowania i informatyki, w Object-Oriented Software Construction . Zasadnicze znaczenie dla zorientowania się na jakość w Eiffel ma mechanizm niezawodności Meyera, Design by Contract , który jest integralną częścią zarówno metody, jak i języka.

TIOBE język programowania Popularności wykres od 2002 do 2018. W 2000 roku obiekt zorientowanych Java (niebieski) i proceduralną C (czarny) rywalizowali o położeniu górnym.

Na początku i w połowie lat 90. XX wieku programowanie obiektowe rozwinęło się jako dominujący paradygmat programowania, gdy języki programowania wspierające te techniki stały się powszechnie dostępne. Obejmowały one Visual FoxPro 3.0, C ++ i Delphi . Jego dominacja została dodatkowo wzmocniona przez rosnącą popularność graficznych interfejsów użytkownika , które w dużym stopniu opierają się na technikach programowania obiektowego. Przykład blisko spokrewnionej biblioteki dynamicznego GUI i języka OOP można znaleźć w frameworkach Cocoa na Mac OS X , napisanych w Objective-C , zorientowanym obiektowo, dynamicznym rozszerzeniu obsługi wiadomości do C, opartym na Smalltalk. Zestawy narzędzi OOP również zwiększyły popularność programowania sterowanego zdarzeniami (chociaż ta koncepcja nie ogranicza się do OOP).

W ETH Zurich , Niklaus Wirth i jego koledzy również bada takie tematy jak abstrakcji danych i programowania modularnego (chociaż to było w powszechnym użyciu w 1960 roku lub wcześniej). Modula-2 (1978) obejmował oba, a ich kolejny projekt, Oberon , zawierał charakterystyczne podejście do orientacji obiektowej, klas i tym podobnych.

Funkcje zorientowane obiektowo zostały dodane do wielu wcześniej istniejących języków, w tym Ada , BASIC , Fortran , Pascal i COBOL . Dodanie tych funkcji do języków, które początkowo nie były dla nich zaprojektowane, często prowadziło do problemów z kompatybilnością i utrzymywalnością kodu.

Niedawno pojawiło się wiele języków, które są głównie zorientowane obiektowo, ale są również kompatybilne z metodologią proceduralną. Dwa takie języki to Python i Ruby . Prawdopodobnie najważniejszymi komercyjnie najnowszymi językami obiektowymi są Java , opracowane przez Sun Microsystems , a także C # i Visual Basic.NET (VB.NET), oba zaprojektowane dla platformy .NET firmy Microsoft . Każdy z tych dwóch frameworków na swój sposób pokazuje korzyści płynące z używania OOP poprzez tworzenie abstrakcji od implementacji. VB.NET i C # obsługują dziedziczenie międzyjęzykowe, umożliwiając klasom zdefiniowanym w jednym języku podklasy zdefiniowane w innym języku.

Języki OOP

Simula (1967) jest powszechnie uznawany za pierwszy język z podstawowymi cechami języka zorientowanego obiektowo. Został stworzony do tworzenia programów symulacyjnych , w których to, co zaczęto nazywać obiektami, było najważniejszą reprezentacją informacji. Smalltalk (1972–1980) to kolejny wczesny przykład, za pomocą którego opracowano znaczną część teorii OOP. Jeśli chodzi o stopień zorientowania obiektu, można dokonać następujących rozróżnień:

OOP w językach dynamicznych

W ostatnich latach programowanie obiektowe stało się szczególnie popularne w dynamicznych językach programowania . Python , PowerShell , Ruby i Groovy to dynamiczne języki zbudowane na zasadach OOP, podczas gdy Perl i PHP dodawały funkcje obiektowe od wersji Perl 5 i PHP 4, a ColdFusion od wersji 6.

Document Object Model z HTML , XHTML i XML dokumentów w Internecie ma powiązania do popularnej JavaScript / ECMAScript języku. JavaScript jest prawdopodobnie najbardziej znanym językiem programowania opartym na prototypach , który wykorzystuje klonowanie z prototypów zamiast dziedziczenia po klasie (w przeciwieństwie do programowania opartego na klasach ). Innym językiem skryptowym, który przyjmuje takie podejście, jest Lua .

OOP w protokole sieciowym

Komunikaty przepływające między komputerami w celu żądania usług w środowisku klient-serwer można zaprojektować jako linearyzacje obiektów zdefiniowanych przez obiekty klas znane zarówno klientowi, jak i serwerowi. Na przykład prosty zlinearyzowany obiekt składałby się z pola długości, punktu kodowego identyfikującego klasę i wartości danych. Bardziej złożonym przykładem byłoby polecenie składające się z długości i punktu kodowego polecenia oraz wartości składające się z zlinearyzowanych obiektów reprezentujących parametry polecenia. Każde takie polecenie musi być skierowane przez serwer do obiektu, którego klasa (lub nadklasa) rozpoznaje polecenie i jest w stanie dostarczyć żądaną usługę. Klienty i serwery najlepiej modelować jako złożone struktury obiektowe. Rozproszona architektura zarządzania danymi (DDM) przyjęła to podejście i użyła obiektów klas do zdefiniowania obiektów na czterech poziomach formalnej hierarchii:

  • Pola definiujące wartości danych, które tworzą komunikaty, takie jak ich długość, punkt kodowy i wartości danych.
  • Obiekty i zbiory obiektów podobne do tych, które można znaleźć w programie Smalltalk dla komunikatów i parametrów.
  • Menedżery podobne do obiektów IBM i , takie jak katalog na pliki i pliki składające się z metadanych i rekordów. Menedżerowie koncepcyjnie zapewniają pamięć i zasoby przetwarzania dla zawartych w nich obiektów.
  • Klient lub serwer składający się ze wszystkich menedżerów niezbędnych do wdrożenia pełnego środowiska przetwarzania, obsługującego takie aspekty jak usługi katalogowe, bezpieczeństwo i kontrolę współbieżności.

Początkowa wersja rozproszonych usług plików zdefiniowanych przez DDM. Później został rozszerzony, aby stać się podstawą architektury rozproszonej relacyjnej bazy danych (DRDA).

Wzorce projektowe

Wyzwania projektowania zorientowanego obiektowo są rozwiązywane za pomocą kilku podejść. Najpopularniejszy jest znany jako wzorce projektowe skodyfikowane przez Gamma i in. . Szerzej, termin „ wzorce projektowe ” może być używany w odniesieniu do dowolnego ogólnego, powtarzalnego wzorca rozwiązania powszechnie występującego problemu w projektowaniu oprogramowania. Niektóre z tych często występujących problemów mają konsekwencje i rozwiązania specyficzne dla rozwoju zorientowanego obiektowo.

Dziedziczenie i podtyp behawioralny

Intuicyjne jest założenie, że dziedziczenie tworzy semantyczną relację „ jest ”, a zatem wnioskowanie, że obiekty utworzone z podklas mogą być zawsze bezpiecznie używane zamiast obiektów utworzonych z nadklasy. Ta intuicja jest niestety fałszywa w większości języków OOP, w szczególności we wszystkich tych, które dopuszczają zmienne obiekty. Polimorfizm podtypów wymuszany przez moduł sprawdzania typów w językach OOP (ze zmiennymi obiektami) nie może zagwarantować podtypów behawioralnych w żadnym kontekście. Podtyp behawioralny jest generalnie nierozstrzygalny, więc nie może być zaimplementowany przez program (kompilator). Hierarchie klas lub obiektów muszą być starannie zaprojektowane, biorąc pod uwagę możliwe nieprawidłowe zastosowania, których nie można wykryć składniowo. Ten problem jest znany jako zasada substytucji Liskova .

Gang of Four wzorców projektowych

Wzorce projektowe: elementy oprogramowania obiektowego wielokrotnego użytku to wpływowa książka opublikowana w 1994 roku przez Ericha Gamma , Richarda Helma , Ralpha Johnsona i Johna Vlissidesa , często nazywana humorystycznie „Gang of Four”. Oprócz eksploracji możliwości i pułapek programowania zorientowanego obiektowo, opisuje 23 typowe problemy programistyczne i wzorce ich rozwiązywania. W kwietniu 2007 roku książka miała 36. nakład.

W książce opisano następujące wzorce:

Orientacja obiektowa i bazy danych

Zarówno programowanie obiektowe, jak i systemy zarządzania relacyjnymi bazami danych (RDBMS) są obecnie niezwykle powszechne w oprogramowaniu. Ponieważ relacyjne bazy danych nie przechowują obiektów bezpośrednio (chociaż niektóre systemy RDBMS mają funkcje zorientowane obiektowo, aby to przybliżyć), istnieje ogólna potrzeba połączenia tych dwóch światów. Problem łączenia dostępów w programowaniu obiektowym i wzorców danych z relacyjnymi bazami danych jest znany jako niedopasowanie impedancji obiektowo-relacyjnej . Istnieje wiele sposobów radzenia sobie z tym problemem, ale nie ma ogólnego rozwiązania bez wad. Jednym z najczęstszych podejść jest mapowanie obiektowo-relacyjne , które można znaleźć w językach IDE , takich jak Visual FoxPro i bibliotekach, takich jak Java Data Objects i ActiveRecord Ruby on Rails .

Istnieją również obiektowe bazy danych , których można użyć do zastąpienia systemów RDBMS, ale nie odniosły one takiego sukcesu technicznego i komercyjnego jak systemy RDBMS.

Modelowanie i relacje w świecie rzeczywistym

OOP może służyć do kojarzenia rzeczywistych obiektów i procesów z cyfrowymi odpowiednikami. Jednak nie wszyscy zgadzają się, że OOP ułatwia bezpośrednie mapowanie świata rzeczywistego (patrz sekcja Krytyka ) lub że mapowanie świata rzeczywistego jest nawet godnym celem; Bertrand Meyer argumentuje w Object-Oriented Software Construction, że program nie jest modelem świata, ale modelem jakiejś części świata; „Rzeczywistość jest kuzynem dwukrotnie usuniętym”. Jednocześnie zauważono kilka głównych ograniczeń OOP. Na przykład problem koło-elipsa jest trudny do rozwiązania przy użyciu koncepcji dziedziczenia OOP .

Jednak Niklaus Wirth (który spopularyzował powiedzenie znane obecnie jako prawo Wirtha : „Oprogramowanie staje się wolniejsze szybciej niż sprzęt staje się szybszy”) powiedział o OOP w swoim artykule „Dobre pomysły przez lustro”: „Ten paradygmat ściśle odzwierciedla struktury systemów „w świecie rzeczywistym” i dlatego dobrze nadaje się do modelowania złożonych systemów o złożonych zachowaniach ”(kontrast z zasadą KISS ).

Steve Yegge i inni zauważyli, że w językach naturalnych brakuje podejścia OOP polegającego na nadawaniu priorytetów rzeczom (obiektom / rzeczownikom ) przed działaniami (metodami / czasownikami ). Ten problem może powodować, że OOP cierpi na bardziej zawiłe rozwiązania niż programowanie proceduralne.

OOP i kontrola przepływu

OOP został opracowany w celu zwiększenia możliwości ponownego wykorzystania i konserwacji kodu źródłowego. Przejrzysta reprezentacja przepływu sterowania nie miała priorytetu i miała być obsługiwana przez kompilator. Wraz ze wzrostem znaczenia sprzętu równoległego i kodowania wielowątkowego , rozwój przejrzystego przepływu sterowania staje się ważniejszy, co jest trudne do osiągnięcia dzięki OOP.

Projektowanie oparte na odpowiedzialności a projektowanie oparte na danych

Projekt oparty na odpowiedzialności definiuje klasy w kontekście kontraktu, to znaczy klasa powinna być zdefiniowana wokół odpowiedzialności i informacji, które ona udostępnia. Kontrastuje to Wirfs-Brock i Wilkerson z projektowaniem opartym na danych , w którym klasy są definiowane wokół struktur danych, które muszą być utrzymywane. Autorzy uważają, że preferowane jest projektowanie oparte na odpowiedzialności.

Wytyczne SOLID i GRASP

SOLID to mnemonik wymyślony przez Michaela Feathersa, który oznacza i popiera pięć praktyk programowania:

GRASP (General Responsibility Assignment Software Patterns) to kolejny zestaw wytycznych zalecanych przez Craiga Larmana .

Krytyka

Paradygmat OOP był krytykowany z wielu powodów, w tym z powodu niespełnienia wyznaczonych celów ponownego wykorzystania i modułowości oraz z powodu nadmiernego podkreślania jednego aspektu projektowania i modelowania oprogramowania (dane / obiekty) kosztem innych ważnych aspektów (obliczenia / algorytmy) .

Luca Cardelli twierdził, że kod OOP jest „z natury mniej wydajny” niż kod proceduralny, że kompilacja OOP może trwać dłużej, a języki OOP mają „wyjątkowo słabe właściwości modularności w odniesieniu do rozszerzania i modyfikacji klas” i wydają się być niezwykle złożone . Ten ostatni punkt powtarza Joe Armstrong , główny wynalazca Erlanga , cytując go:

Problem z językami zorientowanymi obiektowo polega na tym, że mają one całe to ukryte środowisko, które niosą ze sobą. Chciałeś banana, ale dostałeś goryla trzymającego banana i całą dżunglę.

Badanie przeprowadzone przez Potok i wsp. nie wykazał znaczącej różnicy w produktywności między metodami otwartymi i proceduralnymi.

Christopher J. Date stwierdził, że krytyczne porównanie OOP z innymi technologiami, w szczególności relacyjnymi, jest trudne z powodu braku uzgodnionej i rygorystycznej definicji OOP; jednak Date i Darwen zaproponowali teoretyczne podstawy OOP, które wykorzystują OOP jako rodzaj dostosowywalnego systemu typów do obsługi RDBMS .

W artykule Lawrence Krubner stwierdził, że w porównaniu z innymi językami (dialekty LISP, języki funkcjonalne itp.) Języki OOP nie mają wyjątkowych zalet i powodują duże obciążenie niepotrzebnej złożoności.

Alexander Stepanov niekorzystnie porównuje orientację obiektową z programowaniem ogólnym :

Uważam, że OOP technicznie nie jest rozsądne. Próbuje zdekomponować świat pod względem interfejsów, które różnią się w ramach jednego typu. Aby poradzić sobie z prawdziwymi problemami, potrzebujesz wielosortowych algebr - rodzin interfejsów obejmujących wiele typów. Uważam, że OOP jest filozoficznie nieuzasadnione. Twierdzi, że wszystko jest przedmiotem. Nawet jeśli to prawda, nie jest to zbyt interesujące - powiedzenie, że wszystko jest przedmiotem, w ogóle nic nie mówi.

Paul Graham zasugerował, że popularność OOP w dużych firmach wynika z „dużych (i często zmieniających się) grup przeciętnych programistów”. Według Grahama dyscyplina narzucona przez OOP uniemożliwia programowi „wyrządzenie zbyt dużej szkody”.

Leo Brodie zasugerował związek między samodzielną naturą obiektów a tendencją do powielania kodu z naruszeniem zasady „ nie powtarzaj się ” w tworzeniu oprogramowania.

Steve Yegge zauważył, że w przeciwieństwie do programowania funkcjonalnego :

Programowanie obiektowe stawia rzeczowniki na pierwszym miejscu. Dlaczego miałbyś posunąć się tak daleko, aby umieścić jedną część przemówienia na piedestale? Dlaczego jeden rodzaj koncepcji miałby mieć pierwszeństwo przed innym? Nie jest tak, że OOP nagle sprawił, że czasowniki stały się mniej ważne w sposób, w jaki faktycznie myślimy. To dziwnie wypaczona perspektywa.

Rich Hickey , twórca Clojure , opisał systemy obiektowe jako zbyt uproszczone modele świata rzeczywistego. Podkreślił niezdolność OOP do prawidłowego modelowania czasu, co staje się coraz bardziej problematyczne, gdy systemy oprogramowania stają się coraz bardziej współbieżne.

Eric S. Raymond , programista uniksowy i zwolennik oprogramowania open source , odniósł się krytycznie do twierdzeń, które przedstawiają programowanie obiektowe jako „jedyne prawdziwe rozwiązanie”, i napisał, że języki programowania zorientowane obiektowo mają tendencję do zachęcania do programów grubowarstwowych, które zniszczyć przejrzystość. Raymond porównuje to niekorzystnie na podejściu przyjętym z Unix i język programowania C .

Rob Pike , programista zaangażowany w tworzenie UTF-8 i Go , nazwał programowanie obiektowe „ rzymskimi cyframi obliczeniowymi” i powiedział, że języki OOP często przenoszą nacisk ze struktur danych i algorytmów na typy . Ponadto przytacza przykład profesora Javy, którego „idiomatyczne” rozwiązanie problemu polegało na utworzeniu sześciu nowych klas, zamiast po prostu użyć tabeli przeglądowej .

Semantyka formalna

Obiekty są jednostkami czasu wykonywania w systemie zorientowanym obiektowo. Mogą reprezentować osobę, miejsce, konto bankowe, tabelę danych lub dowolną pozycję, którą program musi obsługiwać.

Podjęto kilka prób sformalizowania pojęć używanych w programowaniu obiektowym. Następujące koncepcje i konstrukcje zostały użyte jako interpretacje pojęć OOP:

Próby znalezienia spójnej definicji lub teorii stojącej za przedmiotami nie okazały się zbyt skuteczne (zobacz jednak Abadi i Cardelli, A Theory of Objects, gdzie znajdują się formalne definicje wielu koncepcji i konstruktów OOP) i często są bardzo rozbieżne. Na przykład niektóre definicje koncentrują się na czynnościach umysłowych, a inne na konstruowaniu programu. Jedną z prostszych definicji jest to, że OOP jest czynnością polegającą na używaniu "mapowych" struktur danych lub tablic, które mogą zawierać funkcje i wskaźniki do innych map, a wszystko to z pewnym cukrem składniowym i określającym zakres . Dziedziczenie można wykonać przez sklonowanie map (czasami nazywane „prototypowaniem”).

Zobacz też

Systemy

Języki modelowania

Bibliografia

Dalsza lektura

Linki zewnętrzne