Programowanie obiektowe

Z Wikipedii, wolnej encyklopedii
Skocz do: nawigacji, wyszukiwania

Programowanie obiektowe (ang. object-oriented programming) — paradygmat programowania, w którym programy definiuje się za pomocą obiektów — elementów łączących stan (czyli dane, nazywane najczęściej polami) i zachowanie (czyli procedury, tu: metody). Obiektowy program komputerowy wyrażony jest jako zbiór takich obiektów, komunikujących się pomiędzy sobą w celu wykonywania zadań.

Podejście to różni się od tradycyjnego programowania proceduralnego, gdzie dane i procedury nie są ze sobą bezpośrednio związane. Programowanie obiektowe ma ułatwić pisanie, konserwację i wielokrotne użycie programów lub ich fragmentów.

Największym atutem programowania, projektowania oraz analizy obiektowej jest zgodność takiego podejścia z rzeczywistością – mózg ludzki jest w naturalny sposób najlepiej przystosowany do takiego podejścia przy przetwarzaniu informacji.

Podstawowe założenia paradygmatu obiektowego[edytuj | edytuj kod]

Istnieje pewna różnica zdań co do tego, jakie cechy języków programowania czynią je obiektowymi. Powszechnie uważa się, że najważniejsze są następujące cechy:

Abstrakcja[edytuj | edytuj kod]

Każdy obiekt w systemie służy jako model abstrakcyjnego "wykonawcy", który może wykonywać pracę, opisywać i zmieniać swój stan oraz komunikować się z innymi obiektami w systemie bez ujawniania, w jaki sposób zaimplementowano dane cechy. Procesy, funkcje lub metody mogą być również abstrahowane, a kiedy tak się dzieje, konieczne są rozmaite techniki rozszerzania abstrakcji.

Hermetyzacja[edytuj | edytuj kod]

Czyli ukrywanie implementacji, enkapsulacja. Zapewnia, że obiekt nie może zmieniać stanu wewnętrznego innych obiektów w nieoczekiwany sposób. Tylko własne metody obiektu są uprawnione do zmiany jego stanu. Każdy typ obiektu prezentuje innym obiektom swój interfejs, który określa dopuszczalne metody współpracy. Pewne języki osłabiają to założenie, dopuszczając pewien poziom bezpośredniego (kontrolowanego) dostępu do "wnętrzności" obiektu. Ograniczają w ten sposób poziom abstrakcji. Przykładowo w niektórych kompilatorach języka C++ istnieje możliwość tymczasowego wyłączenia mechanizmu enkapsulacji; otwiera to dostęp do wszystkich pól i metod prywatnych, ułatwiając programistom pracę nad pośrednimi etapami tworzenia kodu i znajdowaniem błędów.

Polimorfizm[edytuj | edytuj kod]

Referencje i kolekcje obiektów mogą dotyczyć obiektów różnego typu, a wywołanie metody dla referencji spowoduje zachowanie odpowiednie dla pełnego typu obiektu wywoływanego. Jeśli dzieje się to w czasie działania programu, to nazywa się to późnym wiązaniem lub wiązaniem dynamicznym. Niektóre języki udostępniają bardziej statyczne (w trakcie kompilacji) rozwiązania polimorfizmu – na przykład szablony i przeciążanie operatorów w C++.

Dziedziczenie[edytuj | edytuj kod]

Porządkuje i wspomaga polimorfizm i enkapsulację dzięki umożliwieniu definiowania i tworzenia specjalizowanych obiektów na podstawie bardziej ogólnych. Dla obiektów specjalizowanych nie trzeba redefiniować całej funkcjonalności, lecz tylko tę, której nie ma obiekt ogólniejszy. W typowym przypadku powstają grupy obiektów zwane klasami, oraz grupy klas zwane drzewami. Odzwierciedlają one wspólne cechy obiektów.

Historia programowania obiektowego[edytuj | edytuj kod]

Koncepcja programowania obiektowego pierwotnie pojawiła się w Simuli 67, języku zaprojektowanym do zastosowań symulacyjnych, stworzonym przez Ole-Johana Dahla i Kristena Nygaarda z Norsk Regnesentral w Oslo. (Mówi się, że pracowali oni nad symulacjami zachowania się statków i mieli kłopoty z opanowaniem wszystkich zależności, jakie wywierały na siebie nawzajem wszystkie parametry statków w symulacji. Wtedy wpadli na pomysł, by pogrupować typy statków w różne klasy obiektów, a każda z klas sama odpowiadałaby za określanie własnych danych i zachowań.) Później koncepcja została dopracowana w języku Smalltalk, stworzonym w Simuli w Xerox PARC, ale zaprojektowanym jako w pełni dynamiczny system, w którym obiekty mogą być tworzone i modyfikowane "w locie", a nie system oparty na statycznych programach.

Programowanie obiektowe zyskało status techniki dominującej w połowie lat 80., głównie ze względu na wpływ C++, stanowiącego rozszerzenie języka C. Dominacja C++ została utrwalona przez wzrost popularności graficznych interfejsów użytkownika, do tworzenia których programowanie obiektowe nadaje się szczególnie dobrze.

W tym okresie cechy obiektowe dodano do wielu języków programowania, w tym Ady, BASIC-a, Lispu, Pascala i innych. Dodanie obiektowości do języków, które pierwotnie nie były do niej przystosowane, zrodziło szereg problemów z kompatybilnością i konserwacją kodu. Z kolei "czysto" obiektowym językom brakowało cech, z których programiści przyzwyczajeni byli korzystać. By zapełnić tę lukę, podejmowano liczne próby stworzenia języków obiektowych dostarczających jednocześnie "bezpiecznych" elementów proceduralności. Eiffel Bertranda Meyera był wczesnym przykładem dość udanego języka spełniającego te założenia; obecnie został on w zasadzie całkowicie zastąpiony przez Javę.

Podobnie, jak programowanie funkcyjne doprowadziło do udoskonalenia technik takich, jak programowanie strukturalne, do współczesnych metod projektowania oprogramowania obiektowego zaliczają się takie usprawnienia, jak wzorce projektowe (ang. design patterns), design by contract i języki modelowania (np. UML).

Obiektowość rozprzestrzeniła się dość znacznie, jednak zwykle w systemach hybrydowych, w połączeniu z programowaniem niskopoziomowym (asembler), funkcyjnym (OCaml, niektóre dialekty Lispu), sieciowym (Java), skryptowym (Perl, Python, Ruby) itd. Systemy czysto obiektowe jak Smalltalk nie znalazły zbyt szerokiego zastosowania.

Podział[edytuj | edytuj kod]

Można wyróżnić dwa zasadnicze podtypy programowania obiektowego

Programowanie oparte na klasach[edytuj | edytuj kod]

Definiowane są klasy, czyli typy zmiennych, a następnie tworzone są obiekty, czyli zmienne (w uproszczeniu) tych typów.

Programowanie oparte na prototypach[edytuj | edytuj kod]

W tym podejściu nie istnieje pojęcie klasy. Nowe obiekty tworzy się w oparciu o istniejący już obiekt – prototyp, po którym dziedziczone są pola i metody i można go rozszerzać o nowe. Spotykany raczej w językach interpretowanych np. JavaScript.

Elementarna charakterystyka popularnych języków obiektowych[edytuj | edytuj kod]

Poniższa charakterystyka dopuszcza bardzo dużą różnorodność – i w rzeczywistości, o ile systemy programowania strukturalnego czy funkcyjnego były do siebie stosunkowo podobne, o tyle systemy obiektowe różnią się w dużym stopniu.

  • Dziedziczenie wielokrotne:
  • Klasa jest obiektem:
    • tak: Java (za pomocą obiektu Class), Lisp, Objective-C, Python, Ruby
    • nie: C++, C#, ObjectPascal, OCaml, PHP5
  • Wszystkie obiekty wywodzą się z jednego korzenia i muszą mieć nadklasę:
    • tak: C#, Incr Tcl, Java, Lisp, Objective-C, ObjectPascal, Perl (klasa UNIVERSAL), Python (klasy nowego typu), Ruby
    • nie: C++, OCaml, PHP5, Python (klasy starego typu)
  • Obiekt można pytać o to, do której podklasy należy:
    • tak: C++ (RTTI), C#, Incr Tcl, Java (RTTI lub mechanizm refleksji), Lisp, Objective-C, ObjectPascal (RTTI), Perl (metoda isa), PHP5 (mechanizm refleksji), Python, Ruby
    • nie: OCaml
  • Typy generyczne (uogólnione):
    • tak: C# 2.0, Java 1.5, ObjectPascal (Delphi 2009, FreePascal 2.2)
    • tak (przez mechanizm szablonów): C++, D
    • nie dotyczy: PHP5
  • Przeciążanie operatorów:
    • tak: C++, C#, Lisp, ObjectPascal (od BDS 2006), Perl, Python, Ruby
    • nie: Java (choć przeciążonych jest kilka operatorów wbudowanych, np. + w klasie String), Objective-C, ObjectPascal (do BDS 2006), OCaml, PHP5 (podobnie jak w Javie przeciążone są niektóre operatory – wywołania składowych i metod, od PHP 5.2 także operacje tablicowe)

Zobacz też[edytuj | edytuj kod]

Linki zewnętrzne[edytuj | edytuj kod]