Komputery i nowoczesne gadżety

Programowanie obiektowe (OOP) jest obecnie najpopularniejszą technologią programowania. Programowanie obiektowe jest rozwinięciem technologii programowania strukturalnego, ma jednak swoje własne charakterystyczne cechy.

Najpopularniejszymi obiektowymi systemami programowania wizualnego są Microsoft Visual Basic i Borland Delphi.

Podstawą programowania obiektowego jest tworzenie aplikacji z obiektów, tak jak domy buduje się z bloków i różnych części. Niektóre obiekty trzeba stworzyć całkowicie samodzielnie, inne zaś można wypożyczyć w formie gotowej z różnych bibliotek.

Ważne miejsce w technologii programowania obiektowego zajmują wydarzenie. Zdarzeniami mogą być kliknięcie obiektu myszą, naciśnięcie określonego klawisza, otwarcie dokumentu itp. W reakcji na zdarzenia wywoływana jest określona procedura, która może zmienić właściwości obiektu, wywołać jego metody itp.

Systemy programowania obiektowego zazwyczaj wykorzystują interfejs graficzny do wizualizacji procesu programowania. Możliwe staje się tworzenie obiektów, ustawianie ich właściwości i zachowania za pomocą myszki.

Obiekt z jednej strony posiada pewne właściwości charakteryzujące jego stan w danym momencie, z drugiej strony możliwe są operacje prowadzące do zmiany właściwości.

Podstawową jednostką w programowaniu obiektowym jest obiekt, w którym zawarte są zarówno dane go opisujące (właściwości), jak i środki przetwarzania tych danych (metody).

Hermetyzacja to połączenie właściwości obiektu i możliwych operacji (metod) na nim.

Kolejną zasadą leżącą u podstaw OOP jest możliwość stworzenia nowej klasy obiektów z dziedziczeniem właściwości i metod jakiejś już istniejącej klasy.

Dziedziczenie to zdolność do wyprowadzania jednej klasy z drugiej przy jednoczesnym zachowaniu wszystkich właściwości i metod klasy przodka (progenitor, czasami nazywanej nadklasą) i dodaniu, jeśli to konieczne, nowych właściwości i metod.

Zbiór klas powiązanych dziedziczeniem nazywa się hierarchią. Dziedziczenie ma odzwierciedlać taką właściwość świata rzeczywistego, jak hierarchia.

Kolejną zasadą OOP jest zasada polimorfizmu.

Polimorfizm to zjawisko, w którym funkcji (metodzie) o tej samej nazwie odpowiada inny kod programu (kod polimorficzny) w zależności od tego, jaki obiekt klasy zostanie użyty przy wywołaniu tej metody.

Polimorfizm zapewnia się poprzez zmianę implementacji metody klasy przodka w klasie potomka z obowiązkowym zachowaniem sygnatury metody. Dzięki temu interfejs klasy przodka pozostaje niezmieniony i pozwala na powiązanie nazwy metody w kodzie z różnymi klasami - z obiektu, której klasy następuje wywołanie, z tej klasy pobierana jest metoda o podanej nazwie. Mechanizm ten nazywany jest łączeniem dynamicznym (lub późnym) – w przeciwieństwie do łączenia statycznego (wczesnego), które jest wykonywane w czasie kompilacji

Podejście obiektowe pozwala połączyć model statyczny opisujący właściwości obiektu z modelem dynamicznym opisującym ich zmiany.

Przy takim podejściu dostęp do zmiany właściwości obiektu możliwy jest jedynie poprzez metody należące do tego obiektu. Metody „otaczają” właściwości obiektu; Mówi się, że właściwości są „zamknięte” w obiekcie.

Zatem w programowaniu obiektowym centralne miejsce zajmują obiekty, które łączą w jedną całość (hermetyzują) właściwości obiektu i możliwe na nim operacje (metody).

Obiekty zawierające tę samą listę właściwości i operacji są łączone zajęcia. Każdy indywidualny obiekt jest instancja klasy. Instancje klasy mogą mieć różne wartości właściwości.

Na przykład system plików komputera może zawierać setki lub tysiące plików. Wszystkie pliki mają ten sam zestaw właściwości (nazwa, pozycja w systemie plików itp.) i operacji (zmiana nazwy, przenoszenie lub kopiowanie itp.) i tworzą klasę obiektów Akta.

Każdy pojedynczy plik jest instancją tej klasy i ma określone wartości właściwości (nazwa, lokalizacja itp.).

Często zdarza się, że te same operacje można wykonać na obiektach różnych klas. Większość klas obiektów w środowisku Windows (foldery, dokumenty, symbole itp.) charakteryzuje się także zestawem tych samych operacji (zmiana nazwy, przenoszenie, kopiowanie, usuwanie itp.). Ta jednolitość jest bardzo przyjazna dla użytkownika.

Jednakże oczywiste jest, że mechanizmy realizacji tych operacji nie są takie same dla różnych klas. Na przykład, aby skopiować folder, musisz wykonać sekwencję działań, aby zmienić system plików, a aby skopiować symbol, wprowadzić zmiany w dokumencie. Operacje te wykonają różne programy dostępne odpowiednio w systemie operacyjnym Windows oraz w edytorze tekstu Word.

W ten sposób jest to realizowane wielopostaciowość, te. możliwość wykonywania tych samych operacji na obiektach należących do różnych klas, przy zachowaniu indywidualnych metod ich realizacji dla każdej klasy.

Tworzą się obiekty, które mają ten sam zestaw właściwości i metod klasa obiektu. Tak więc w aplikacji Word istnieje klasa obiektów dokument(Dokumenty), który ma następujące właściwości: Nazwa(Nazwa), Lokalizacjacja(FileNaine) itp. Obiekty tej klasy również posiadają pewien zestaw metod, na przykład: otwarcie dokumentupolicjant(Otwarty) drukowanie dokumentów(Wydruk), ochronadokument(Zapisz) itp.

Obiekty w aplikacjach tworzą pewnego rodzaju hierarchię. Na szczycie hierarchii obiektów znajduje się aplikacja(Aplikacja). Zatem hierarchia obiektów aplikacji Word obejmuje następujące obiekty: aplikacja(Aplikacja), dokument(Dokumenty), fragment dokumentu(Wybór), symbol(Postać) itp.

Hierarchia obiektów aplikacji Excel zawiera następujące obiekty: aplikacja(Aplikacja), książka(Zeszyt ćwiczeń), arkusz(Arkusz) zasięg komórek(Zakres), komórkika(komórka) itp.

Pełne odniesienie do obiektu składa się z szeregu nazw obiektów zagnieżdżonych sekwencyjnie w sobie. Separatorami nazw obiektów w tej serii są kropki; seria zaczyna się od obiektu aplikacji najwyższego poziomu, a kończy nazwą interesującego nas obiektu. Na przykład łącze do dokumentu Пpo6a.doc w programie Word będzie wyglądać następująco:

Aplikacja. Dokumenty(„Ppo6a.doc”)

Aby obiekt mógł wykonać jakąkolwiek operację, należy określić metodę. Wiele metod posiada argumenty umożliwiające określenie parametrów akcji, które mają zostać wykonane. Aby przypisać określone wartości argumentom, stosuje się dwukropek i znak równości, a argumenty oddziela się przecinkiem.

W Visual Basic obiekty charakteryzują się nie tylko właściwościami i metodami, ale także wydarzenia. Zdarzenie to czynność rozpoznawana przez obiekt. Zdarzenie może zostać wygenerowane przez użytkownika (np. naciśnięcie przycisku myszy lub klawisza na klawiaturze) lub być efektem działania innych obiektów aplikacji.

Dla każdego zdarzenia możesz zaprogramować reakcję, czyli reakcję obiektu na zdarzenie, które miało miejsce. Ten program nazywa się procedura zdarzenia. Nazwa procedury zdarzenia składa się zazwyczaj z nazwy obiektu i nazwy zdarzenia. Na przykład dla obiektu przycisku o nazwie Komenda1 i wydarzenia Kliknij(„klik” powstający w momencie najechania kursorem myszy na obraz przycisku i naciśnięciu lewego przycisku myszy) procedura zdarzenia otrzyma nazwę Komenda1_ Kliknij.

W procedurze zdarzenia może uczestniczyć kilka obiektów. Na przykład w procedurze wspomnianej powyżej Komenda1_ Kliknij zespół może być obecny

Tekst1. Tekst= „Witam!”,

w wyniku wykonania what w „polu tekstowym” obiektu o nazwie Tekst1 Pojawi się linia ze słowem „Hello!”.

Programowanie wizualne, którego metody wykorzystywane są przez środowisko programistyczne Visual Basic, pozwala na tworzenie interfejsu graficznego dla tworzonych aplikacji w oparciu o wykorzystanie elementów sterujących, do których zaliczają się m.in. guziki(Przycisk Polecenie), pola wyboru(Pole wyboru) , pola tekstowe(Pole tekstowe) pola kombi(ListBox) i inne. Obiekty te, ich właściwości i metody zostaną omówione w następnym rozdziale. Na razie zauważmy, że elementy sterujące służą najczęściej do odbierania danych od użytkownika i wyświetlania wyników działania aplikacji. Kontrole są więc podstawą do zbudowania interfejsu użytkownika aplikacji.

Głównymi obiektami używanymi w programowaniu wizualnym są formy(Formularz). Formularz to okno, w którym umieszczone są elementy sterujące. Forma to także obiekt charakteryzujący się zestawem właściwości i metod. Podobnie jak w przypadku każdego innego obiektu, możesz na przykład napisać procedurę zdarzenia dla formularza Formularz_ Obciążenie, który jest uruchamiany w momencie wystąpienia zdarzenia Load i w wyniku którego zostaną wykonane instrukcje niezbędne do działania uruchomionej aplikacji.

zasadniczo korzystał z paradygmatu programowania nakazowego — celem było stworzenie kodu, który będzie odpowiednio reagował na dane. To podejście jest dobre do rozwiązywania małych problemów, ale stwarza wiele trudnych do rozwiązania problemów podczas prób tworzenia duże systemy oprogramowania.

Jedna z alternatyw programowanie dyrektywne Jest programowanie obiektowe, Który Naprawdę pomaga radzić sobie z nieliniowo rosnącą złożonością programów w miarę wzrostu ich objętości. Nie należy jednak wyciągać wniosku, że stosowanie paradygmatu programowania obiektowego gwarantuje pomyślne rozwiązanie wszystkich problemów.

Aby zostać profesjonalistą w programowaniu potrzebny jest talent, kreatywność, inteligencja, wiedza, logika, umiejętność budowania i wykorzystywania abstrakcji oraz, co najważniejsze, doświadczenie.

W tej sekcji będziemy kontynuować wprowadzenie do podstawowych koncepcji programowania obiektowego, które rozpoczęliśmy w pierwszym rozdziale książki. W pierwszej kolejności omówione zostaną koncepcje OOP wspólne dla różnych języków programowania, a następnie ich implementacja w języku Java.

Należy mieć świadomość, że zajęcia z programowania obiektowego prowadzone są dla studentów studiów licencjackich przez cały semestr, dlatego też poniższy materiał stanowi jedynie bardzo podstawowe wprowadzenie do świata OOP. Znacznie pełniejsze omówienie wielu zagadnień związanych z projektowaniem obiektowym, inżynierią i programowaniem znajduje się w tej książce, a w trzecim rozdziale książki można znaleźć bardzo jasny opis wszystkich zorientowanych obiektowo aspektów programowania Język Java.

Podstawowe pojęcia OOP

Programowanie obiektowe lub OOP (programowanie obiektowe) - metodyka programowania opiera się na reprezentacji programu jako zbioru obiektów, z których każdy jest implementacją określonego typu, przy użyciu mechanizmu przesyłanie wiadomości i zajęcia organizowane w hierarchia dziedziczenia.

Centralnym elementem OOP jest abstrakcja. Dane są konwertowane na obiekty za pomocą abstrakcji, a sekwencja przetwarzania tych danych zamienia się w zestaw komunikatów przekazywanych pomiędzy tymi obiektami. Każdy z obiektów ma swoje własne, unikalne zachowanie. Obiekty można traktować jako konkretne byty, które odpowiadają na komunikaty nakazujące im wykonanie określonego działania.

OOP charakteryzuje się następującymi zasadami (według Alana Kaya):

  • wszystko jest przedmiotem;
  • obliczenia realizowane są poprzez interakcję (wymianę danych) pomiędzy obiektami, w której jeden obiekt wymaga wykonania jakiejś akcji przez inny obiekt; obiekty wchodzą w interakcję poprzez wysyłanie i odbieranie wiadomości; komunikat jest prośbą o wykonanie akcji, uzupełnioną o zestaw argumentów, które mogą być potrzebne przy wykonaniu akcji;
  • każdy obiekt ma niezależny pamięć, który składa się z innych obiektów;
  • każdy obiekt jest przedstawicielem klasy wyrażającej ogólne właściwości obiektów danego typu;
  • ustawione w klasie funkcjonalność(zachowanie obiektu); w ten sposób wszystkie obiekty będące instancjami tej samej klasy mogą wykonywać te same działania;
  • klasy są zorganizowane w pojedynczą strukturę drzewa ze wspólnym korzeniem, tzw hierarchia dziedziczenia; pamięć i zachowanie powiązane z instancjami określonej klasy są automatycznie dostępne dla dowolnej klasy znajdującej się niżej w drzewie hierarchicznym.

Definicja 10.1. Abstrakcja- metoda rozwiązania problemu, w której obiekty różnego rodzaju łączy się wspólnym pojęciem (pojęciem), a następnie zgrupowane byty traktuje się jako elementy jednej kategorii.

Abstrakcja pozwala oddzielić logiczne znaczenie fragmentu programu od problemu jego realizacji, dzieląc opis zewnętrzny(interfejs) obiektu i jego wewnętrzna organizacja(realizacja).

Definicja 10.2. Kapsułkowanie- technika polegająca na ukrywaniu w nim informacji nieistotnych z punktu widzenia interfejsu obiektu.

Definicja 10.3. Dziedzictwo- właściwość obiektów, dzięki której instancje klasy uzyskują dostęp do danych i metod klas przodków bez ich redefiniowania.

Dziedziczenie umożliwia różnym typom danych współdzielenie tego samego kodu, co skutkuje mniejszym kodem i większą funkcjonalnością.

Definicja 10.4.

informacje ogólne

OOP to styl programowania, który pojawił się w latach 80. XX wieku. W przeciwieństwie do języków proceduralnych, w których dane i instrukcje ich przetwarzania istnieją osobno, w programowaniu obiektowym informacje te są łączone w jedną całość.

Podstawowe zasady OOP

Dziedzictwo

Druga zasada OOP, dziedziczenie, to zdolność jednej klasy do korzystania z metod drugiej bez powtarzania ich faktycznej implementacji. Dziedziczenie pozwala pozbyć się nadmiarowości w kodzie źródłowym.

Wielopostaciowość

Kolejną zasadą OOP jest polimorfizm. Jego zastosowanie sprawia, że ​​do manipulowania obiektami o różnym stopniu złożoności można stworzyć jeden interfejs, który będzie inaczej reagował na zdarzenia, a jednocześnie poprawnie realizował przypisane mu zadania.

Języki OOP

Zasady OOP stosowane są w najpopularniejszych językach programowania takich jak C++ i Java, w których tworzona jest znaczna część programów i aplikacji. Istnieją również rzadziej używane języki OOP - Delphi, Object Pascal, Ruby i wiele innych.

Krytyka OOP

Pomimo w większości pozytywnych wypowiedzi na temat tej metodologii, zasady OOP są często krytykowane. Podobnie jak OOP, ma swoje wady.

Po pierwsze, trudność przejścia. Zrozumienie zasad OOP zajmie sporo czasu, szczególnie osobom, które blisko pracują wyłącznie z proceduralnymi językami programowania.

Po drugie, wadą jest bardziej złożona dokumentacja, ponieważ konieczne będzie nie tylko opisanie klas i obiektów, ale także konkretnych przypadków ich implementacji.

Po trzecie, nadmierna uniwersalność metod może prowadzić do tego, że kod źródłowy i tworzone programy zostaną przeciążone funkcjami i możliwościami, na które w tym konkretnym przypadku nie jest zapotrzebowanie. Ponadto zauważają nieefektywność w zakresie alokacji pamięci. Jednak niezależnie od opinii innych, liczba programistów OOP stale rośnie, a same języki szybko się rozwijają.

Cześć! Czy zastanawiałeś się kiedyś, dlaczego Java została zaprojektowana w taki, a nie inny sposób? W tym sensie, że tworzysz klasy, na ich podstawie - obiekty, klasy mają metody itp. Ale dlaczego struktura języka jest taka, że ​​programy składają się z klas i obiektów, a nie z czegoś innego? Dlaczego koncepcja „ obiekt” i wysunąć na pierwszy plan? Czy wszystkie języki działają w ten sposób, a jeśli nie, jakie korzyści daje to Java? Jak widać pytań jest wiele :) Spróbujmy odpowiedzieć na każde z nich w dzisiejszym wykładzie.

Co to jest programowanie obiektowe (OOP)

Oczywiście Java nie bez powodu składa się z obiektów i klas. Nie jest to fanaberia jego twórców, ani nawet ich wynalazek. Istnieje wiele innych języków opartych na obiektach. Nazwano pierwszy taki język Symula i został wynaleziony w latach 60. XX wieku w Norwegii. Simula wprowadziła między innymi koncepcje „ Klasa " I " metoda ». Kristen Nygaard i Ole Johan Dahl – twórcy Simuli

Wydawałoby się, że Symula- język starożytny według standardów programowania, ale ich „rodzinne” powiązanie z Javą widać gołym okiem. Najprawdopodobniej możesz łatwo przeczytać zapisany na nim kod i ogólnie wyjaśnić, co robi :) Begin Class Rectangle (Width, Height) ; Rzeczywista szerokość, wysokość; Rozpocznij Powierzchnia rzeczywista, obwód; Aktualizacja procedury; Obszar początkowy: = szerokość * wysokość; Tekst wyjściowy( „Prostokąt jest aktualizowany, obszar =”) ; OutFix(obszar, 2, 8); OutImage; Obwód: = 2 * (szerokość + wysokość) ; Tekst wyjściowy( „Prostokąt jest aktualizowany, obwód =”) ; OutFix(Obwód, 2, 8); OutImage; Koniec aktualizacji; Aktualizacja; OutText("Utworzono prostokąt: "); OutFix (szerokość, 2, 6); OutFix(wysokość, 2, 6); OutImage; Koniec prostokąta; Klasa Rectangle ColoredRectangle(Color); Kolor tekstu; Rozpocznij tekst wyjściowy ( „Utworzono kolorowy prostokąt, kolor =”) ; Tekst wyjściowy(kolor); OutImage; Koniec kolorowego prostokąta; Ref (prostokąt) Cr; Cr: - Nowy ColoredRectangle(10, 20, "Zielony"); Koniec; Przykładowy kod pochodzi z artykułu Simula - 50 lat OOP. Jak widać Java i jej przodek nie różnią się zbytnio od siebie :) Wynika to z faktu, że pojawienie się Simuli zapoczątkowało narodziny nowej koncepcji - programowanie obiektowe. Wikipedia podaje następującą definicję OOP: Programowanie obiektowe (OOP) - metodologia programowania oparta na reprezentowaniu programu jako zbioru obiektów, z których każdy jest instancją określonej klasy, a klasy tworzą hierarchię dziedziczenia. Moim zdaniem jest bardzo udany. Niedawno zacząłeś uczyć się języka Java, ale nie ma w nim prawie żadnych słów, które byłyby dla Ciebie nieznane :) Dzisiaj Ups- najpopularniejsza metodyka programowania. Oprócz języka Java są one używane w wielu popularnych językach, o których być może słyszałeś. Są to C++ (jest aktywnie wykorzystywany przez twórców gier komputerowych), Objective-C i Swift (piszą programy na urządzenia Apple), Python (najbardziej poszukiwany w uczeniu maszynowym), PHP (jeden z najpopularniejszych języków tworzenia stron internetowych), JavaScript (prościej powiedzieć, czego na nim nie robią) i wiele innych. Właściwie, jakie są te „zasady” OOP? Powiemy ci bardziej szczegółowo.

Zasady OOP

To jest podstawa. 4 główne cechy, które razem tworzą paradygmat programowania obiektowego. Zrozumienie ich jest kluczem do odniesienia sukcesu jako programista.

Zasada 1. Dziedziczenie.

Dobra wiadomość jest taka, że ​​znasz już niektóre zasady OOP! :) Z dziedziczeniem zetknęliśmy się już kilka razy na wykładach i mieliśmy czas, żeby się nim zająć. Dziedzictwo - mechanizm pozwalający na opisanie nowej klasy na podstawie już istniejącej (nadrzędnej). W tym przypadku właściwości i funkcjonalność klasy nadrzędnej są zapożyczane przez nową klasę. Dlaczego dziedziczenie jest potrzebne i jakie korzyści daje? Po pierwsze – ponowne wykorzystanie kodu. Pola i metody opisane w klasach nadrzędnych można używać w klasach potomnych. Jeśli wszystkie typy samochodów mają 10 wspólnych pól i 5 identycznych metod, wystarczy umieścić je w klasie nadrzędnej Automatyczny. Można ich bez problemu używać w klasach potomnych. Solidne zalety: zarówno ilościowe (mniej kodu), jak i w rezultacie jakościowe (zajęcia stają się znacznie prostsze). Jednocześnie mechanizm dziedziczenia jest bardzo elastyczny i brakujące funkcjonalności można dodać osobno w potomkach (niektóre pola lub zachowania specyficzne dla danej klasy). Ogólnie rzecz biorąc, jak w zwykłym życiu: wszyscy jesteśmy pod pewnymi względami podobni do naszych rodziców, ale pod pewnymi względami różnimy się od nich :)

Zasada 2. Abstrakcja

To bardzo prosta zasada. Abstrakcja oznacza podkreślenie głównych, najistotniejszych cech obiektu i odwrotnie - odrzucenie drugorzędnych, nieistotnych cech. Nie wymyślajmy koła na nowo i przypomnijmy sobie przykład ze starego wykładu o zajęciach. Załóżmy, że tworzymy kartotekę pracowników firmy. Aby utworzyć obiekty pracowników, napisaliśmy klasę Pracownik. Jakie cechy są istotne przy ich opisie w aktach firmy? Pełne imię i nazwisko, Data urodzenia, numer ubezpieczenia społecznego, CYNA. Ale jest mało prawdopodobne, abyśmy w tego typu karcie potrzebowali jego wzrostu, koloru oczu i włosów. Firma nie potrzebuje tych informacji o pracowniku. Dlatego dla klasy Pracownik ustawimy zmienne String name, int age, int socialInsuranceNumber i int taxNumber oraz informacje abstrakcyjne, które są dla nas niepotrzebne, jak np. kolor oczu. Jeśli jednak stworzymy dla agencji katalog fotomodelek, sytuacja zmieni się diametralnie. Opisanie zdjęcia modela jest dla nas bardzo ważne wysokość, kolor oczu I kolor włosów i numer NIP nie jest potrzebny. Dlatego w klasie Model tworzymy zmienne Wysokość sznurka, Włosy sznurka, Oczy sznurka.

Zasada 3: Hermetyzacja

Już się z tym spotkaliśmy. Enkapsulacja w Javie oznacza ograniczenie dostępu do danych i możliwości ich zmiany. Jak widać, opiera się na słowie „kapsułka”. W tej „kapsule” ukrywamy kilka ważnych dla nas danych, których nie chcemy, aby ktokolwiek zmieniał. Prosty przykład z życia. Masz imię i nazwisko. Znają je wszyscy, których znasz. Nie mają jednak możliwości zmiany Twojego imienia i nazwiska. Proces ten, można powiedzieć, jest „zamknięty” w biurze paszportowym: tam możesz zmienić tylko swoje imię i nazwisko i tylko Ty możesz to zrobić. Pozostali „użytkownicy” mają dostęp tylko do odczytu Twojego imienia i nazwiska :) Innym przykładem są pieniądze w Twoim mieszkaniu. Pozostawienie ich na widoku na środku pokoju nie jest dobrym pomysłem. Każdy „użytkownik” (osoba, która przyjdzie do Twojego domu) będzie mógł zmienić liczbę Twoich pieniędzy, tj. odebrać je. Lepiej zamknąć je w sejfie. Tylko Ty będziesz mieć dostęp i tylko za pomocą specjalnego kodu. Oczywistymi przykładami enkapsulacji, z którymi już pracowałeś, są modyfikatory dostępu ( prywatny, publiczny itp.), a także gettery-settery. Jeśli pole wieku klasy Cat nie jest hermetyzowane, każdy może napisać: Cat. wiek = - 1000 ; Natomiast mechanizm enkapsulacji pozwala zabezpieczyć pole wieku metodą ustawiającą, w której możemy sprawdzić, czy wiek nie może być liczbą ujemną.

Zasada 4. Polimorfizm

Wielopostaciowość - jest to możliwość pracy z kilkoma typami tak, jakby były tego samego typu. W tym przypadku zachowanie obiektów będzie się różnić w zależności od typu, do którego należą. Brzmi trochę skomplikowanie? Rozwiążmy to teraz. Weźmy najprostszy przykład - zwierzęta. Stwórzmy klasę Animal z jedną metodą – Voice() i dwoma jej potomkami – Cat i Dog. klasa publiczna Animal ( public void głos () ( System. out. println („Głos!” ) ; ) ) klasa publiczna Dog rozszerza Animal ( @Override public void głos () ( System. out. println („Woof-woof!” ) ; ) ) klasa publiczna Cat rozszerza Animal ( @Override public void Voice () ( System. out. println ( "Miau!" ; ) ) Teraz spróbujmy utworzyć referencję Animal i przypisać jej obiekt Dog. klasa publiczna Main ( public static void main (argumenty string) ( Animal dog = new Dog () ; pies. głos () ; ) ) Jak myślisz, która metoda zostanie wywołana? Zwierzę.głos() czy Pies.głos() ? Zostanie wywołana metoda klasy Pies : Łuk-wow! Stworzyliśmy odniesienie do zwierzęcia, ale obiekt zachowuje się jak pies. W razie potrzeby może zachowywać się jak kot, koń lub inne zwierzę. Najważniejsze jest przypisanie referencji ogólnego typu Animal do obiektu określonej klasy potomnej. Jest to logiczne, ponieważ wszystkie psy są zwierzętami. To właśnie mieliśmy na myśli, gdy powiedzieliśmy, że „obiekty będą zachowywać się inaczej w zależności od tego, jakiego typu są”. Gdybyśmy mieli stworzyć obiekt Cat - public static void main (String args) ( Animal cat = new Cat () ; cat. Voice () ; ) metoda Voice() wyświetliłaby „ Miauczeć!». Co oznacza „umiejętność pracy z kilkoma typami tak, jakby były tego samego typu”? To również jest całkiem łatwe. Wyobraźmy sobie, że tworzymy salon fryzjerski dla zwierząt. Nasz zakład fryzjerski musi być w stanie obciąć sierść wszystkich zwierząt, dlatego utworzymy metodę shear() z parametrem Animal - zwierzę, które będziemy strzyżyć. klasa publiczna AnimalBarbershop ( public void shear (Zwierzę zwierzęce) ( System. out. println ( „Fryzura jest gotowa!”) ; )) A teraz możemy przekazać obiekty Cat i Dog do metody ścinania! public static void main (String argumenty) ( Cat cat = new Cat () ; Dog dog = new Dog () ; AnimalBarbershop barbershop = new AnimalBarbershop (); fryzjer. shear (cat) ; barbershop. shear (dog) ; ) Tutaj mamy go Przykład: klasa AnimalBarbershop traktuje typy Kot i Pies tak, jakby były tego samego typu. Jednocześnie kot i pies zachowują się inaczej: mają inny głos.

Przyczyny pojawienia się OOP

Dlaczego powstała ta nowa koncepcja programowania? Ups ? Programiści mieli narzędzia, które działały: na przykład języki proceduralne. Co skłoniło ich do wymyślenia czegoś zasadniczo nowego? Przede wszystkim komplikacja stojących przed nimi zadań. Jeśli 60 lat temu zadanie programisty wyglądało jak „obliczyć równanie matematyczne takie a takie”, teraz mogłoby brzmieć jak „zastosowanie 7 różnych zakończeń do gry S.T.A.L.K.E.R. w zależności od tego, jakie decyzje podjął użytkownik w momentach gry A, B, C, D, E, F i kombinacji tych decyzji. Zadania, jak widać, w ciągu ostatnich dziesięcioleci wyraźnie stały się bardziej złożone. Oznacza to, że typy danych stały się bardziej złożone. To kolejny powód pojawienia się OOP. Przykład z równaniem można łatwo rozwiązać za pomocą zwykłych prymitywów, nie są tu potrzebne żadne obiekty. Ale trudno będzie nawet opisać problem z zakończeniami gry bez wykorzystania wymyślonych przez Ciebie klas. Ale jednocześnie dość łatwo jest to opisać w klasach i obiektach: oczywiście będziemy potrzebować klasy Gra, Klasa Prześladowca, Klasa Kończący się, Klasa Decyzja gracza, Klasa Chwila Gier i tak dalej. Oznacza to, że nawet nie rozpoczynając rozwiązywania problemu, możemy łatwo wyobrazić sobie w głowach „szkice” jego rozwiązania. Rosnąca złożoność problemów zmusiła programistów do podzielenia problemu na części. Jednak w programowaniu proceduralnym nie było to takie proste. Bardzo często program był „drzewem” składającym się z kilku gałęzi ze wszystkimi możliwymi opcjami jego działania. W zależności od określonych warunków program był wykonywany wzdłuż tej lub innej gałęzi. W przypadku małych programów ta opcja była wygodna, ale podzielenie dużego zadania na części było bardzo trudne. Potrzeba ta stała się kolejnym powodem pojawienia się OOP. Koncepcja ta dała programistom możliwość podzielenia programu na kilka „modułów” klas, z których każdy wykonał swoją część zadania. Wszystkie obiekty oddziałujące ze sobą tworzą pracę naszego programu. Dodatkowo napisany przez nas kod można ponownie wykorzystać w innym miejscu programu, co również pozwala zaoszczędzić mnóstwo czasu. Wersja angielska tego wpisu:

Prawdopodobnie połowa wakatów (jeśli nie więcej) wymaga znajomości i zrozumienia OOP. Tak, ta metodologia zdecydowanie urzekła wielu programistów! Zwykle zrozumienie OOP przychodzi wraz z doświadczeniem, ponieważ praktycznie nie ma odpowiednich i dostępnych materiałów na ten temat. A nawet jeśli tak, nie jest pewne, czy czytelnicy natkną się na nie. Mam nadzieję, że uda mi się wytłumaczyć zasady tej wspaniałej metodologii, jak to mówią, na palcach.

Tak więc już na początku artykułu wspomniałem już o pojęciu „metodologia”. W zastosowaniu do programowania termin ten oznacza obecność dowolnego zestawu sposobów organizacji kodu, metod jego pisania, zgodnie z którymi programista będzie w stanie napisać całkowicie użyteczne programy.

OOP (lub programowanie obiektowe) to sposób organizowania kodu programu, w którym głównymi elementami programu są obiekty i klasy, a logika programu opiera się na ich interakcji.


O obiektach i klasach

Klasa- jest to struktura danych, którą może stworzyć sam programista. W terminologii OOP klasa składa się z pola(w uproszczeniu - zmienne) i metody(w uproszczeniu - funkcje). I jak się okazało, połączenie danych i funkcji do pracy nad nimi w jednej strukturze daje niewyobrażalną moc. Obiekt jest konkretną instancją klasy. Idąc za analogią klasy ze strukturą danych, obiekt to specyficzna struktura danych, która ma przypisane pewne wartości do swoich pól. Wyjaśnię na przykładzie:

Załóżmy, że musimy napisać program, który obliczy obwód i pole trójkąta, które są dane przez dwa boki i kąt między nimi. Aby napisać taki program za pomocą OOP, będziemy musieli stworzyć klasę (czyli strukturę) Triangle. Klasa Triangle będzie przechowywać trzy pola (trzy zmienne): bok A, bok B, kąt między nimi; oraz dwie metody (dwie funkcje): obliczyć obwód, obliczyć powierzchnię. Za pomocą tej klasy możemy opisać dowolny trójkąt oraz obliczyć obwód i pole. Zatem konkretny trójkąt o określonych bokach i kącie między nimi będzie nazywany instancją klasy Triangle. Zatem klasa jest szablonem, a instancja jest konkretną implementacją szablonu. Ale instancje to obiekty, czyli określone elementy przechowujące określone wartości.

Jednym z najpopularniejszych języków programowania obiektowego jest Java. Tam po prostu nie można obejść się bez użycia obiektów. Tak wyglądałby kod klasy opisującej trójkąt w tym języku:

/** * Klasa trójkąta. */ class Triangle ( /** * Specjalna metoda zwana konstruktorem klasy. * Jako dane wejściowe przyjmuje trzy parametry: * długość boku A, długość boku B, * kąt pomiędzy tymi bokami (w stopniach) */ Triangle(podwójny bokA, podwójny sideB , double angleAB) ( this.sideA = sideA; this.sideB = sideB; this.angleAB = angleAB; ) double sideA; //Pole klasy, przechowuje wartość boku A w opisywanym trójkącie double sideB; //Pole klasy , przechowuje wartość boku B w opisywanym trójkącie double angleAB; //Pole klasy przechowuje kąt (w stopniach) pomiędzy dwoma bokami opisywanego trójkąta /** * Metoda klasy obliczająca pole trójkąta */ double getSquare() ( double Square = this.sideA * this .sideB * Math.sin(this.angleAB * Math.PI / 180); return kwadrat; ) /** * Metoda klasy obliczająca obwód trójkąta */ double getPerimeter() ( double sideC = Math.sqrt(Math.pow (this.sideA, 2) + Math.pow(this.sideB, 2) - 2 * this.sideA * this.sideB * Math.cos(this.sideB. kątAB * Matematyka.PI / 180)); podwójny obwód = ta.stronaA + ta.stronaB + stronaC; obwód powrotu; ) )

Jeśli dodamy następujący kod wewnątrz klasy:

/** * Tutaj uruchamiany jest program */ public static void main(String args) ( //Wartości 5, 17, 35 trafiają do konstruktora klasy Triangle Triangle Triangle1 = new Triangle(5, 17, 35 ); System.out .println("Pole trójkąta1: "+triangle1.getSquare()); System.out.println("Obwód trójkąta1: "+triangle1.getPerimeter()); //Wartości 6 , 8, 60 przejdź do konstruktora klasy Triangle Triangleangle2 = nowy Triangle(6, 8, 60); System.out.println("Obszar trójkąta1: "+triangle2.getSquare()); System.out.println („Obwód trójkąta1: „+triangle2.getPerimeter()); )

wówczas program można już uruchomić do wykonania. Jest to cecha języka Java. Jeśli klasa ma taką metodę

Publiczna statyczna pusta główna (argumenty ciągu)

wtedy ta klasa może zostać wykonana. Przyjrzyjmy się kodowi bardziej szczegółowo. Zacznijmy od linii

Trójkąt trójkąt1 = nowy Trójkąt(5, 17, 35);

Tutaj tworzymy instancję trójkąta1 klasy Triangle i od razu nadajemy mu parametry boków oraz kąt między nimi. Jednocześnie wywoływana jest specjalna metoda zwana konstruktorem, która wypełnia pola obiektu wartościami przekazanymi do konstruktora. A co z liniami?

System.out.println("Pole trójkąta1: "+triangle1.getSquare()); System.out.println("Obwód trójkąta1: "+trójkąt1.getPerimeter());

wyprowadź obliczony obszar trójkąta i jego obwód na konsolę.

To samo dzieje się z drugą instancją klasy Triangle.

Zrozumienie istoty zajęć i konstrukcji konkretnych obiektów jest pewnym pierwszym krokiem do zrozumienia metodologii OOP.

Jeszcze raz najważniejsze:

Ups- jest to sposób organizacji kodu programu;

Klasa- jest to niestandardowa struktura danych, która skupia dane i funkcje do pracy z nimi (pola klas i metody klas);

Obiekt jest konkretną instancją klasy, której polom nadano określone wartości.


Trzy magiczne słowa

OOP obejmuje trzy kluczowe podejścia: dziedziczenie, enkapsulację i polimorfizm. Na początek podam definicje z Wikipedii:

Hermetyzacja to właściwość systemowa umożliwiająca łączenie w klasie danych i metod, które z nimi współpracują. Niektóre języki (np. C++) utożsamiają enkapsulację z ukrywaniem, ale większość (Smalltalk, Eiffel, OCaml) rozróżnia te pojęcia.

Dziedziczenie to właściwość systemowa, która pozwala opisać nową klasę w oparciu o istniejącą, z częściowo lub całkowicie zapożyczoną funkcjonalnością. Klasa, z której pochodzi dziedziczenie, nazywana jest klasą bazową, klasą nadrzędną lub nadklasą. Nowa klasa to klasa potomka, dziedzica, dziecka lub klasy pochodnej.

Polimorfizm to właściwość systemu, która pozwala na używanie obiektów o tym samym interfejsie bez informacji o typie i wewnętrznej strukturze obiektu.

Zrozumienie, co właściwie oznaczają te wszystkie definicje, jest dość trudne. W specjalistycznych książkach poruszających ten temat często każdej definicji poświęca się cały rozdział, ale przynajmniej akapit. Chociaż sedna tego, co programista musi zrozumieć i utrwalić na zawsze w swoim mózgu, jest bardzo niewiele.
Jako przykład do analizy użyjemy figur na płaszczyźnie. Ze szkolnej geometrii wiemy, że dla wszystkich figur opisanych na płaszczyźnie można obliczyć obwód i pole. Przykładowo dla punktu oba parametry są równe zeru. W przypadku odcinka możemy jedynie obliczyć obwód. A dla kwadratu, prostokąta lub trójkąta - jedno i drugie. Teraz opiszemy to zadanie w kategoriach OOP. Przydatne jest również uchwycenie łańcucha rozumowania, którego wynikiem jest hierarchia klas, która z kolei jest zawarta w działającym kodzie. Iść:


Zatem punkt to najmniejsza figura geometryczna, która jest podstawą wszystkich innych konstrukcji (figur). Dlatego punkt został wybrany jako podstawowa klasa nadrzędna. Napiszmy klasę punktów w Javie:

/** * Klasa punktu. Klasa bazowa */ class Point ( /** * Pusty konstruktor */ Point() () /** * Metoda klasy obliczająca pole figury */ double getSquare() ( return 0; ) /** * Metoda klasowa obliczająca obwód figury */ double getPerimeter() ( return 0; ) /** * Metoda klasy zwracająca opis figury */ String getDescription() ( return "Point"; ) )

Powstała klasa Point ma pusty konstruktor, ponieważ w tym przykładzie pracujemy bez określonych współrzędnych, a jedynie z parametrami i wartościami bocznymi. Ponieważ punkt nie ma boków, nie ma potrzeby przekazywania mu żadnych parametrów. Należy również zauważyć, że klasa ma metody Point::getSquare() i Point::getPerimeter() do obliczania pola i obwodu, obie zwracają 0. W przypadku punktu jest to logiczne.


Ponieważ nasz punkt jest podstawą wszystkich pozostałych figur, klasy tych pozostałych figur dziedziczymy z klasy Point. Opiszmy klasę odcinka odziedziczonego z klasy punktu:

/** * Klasa Line Segment */ class LineSegment Extends Point ( LineSegment(double segmentLength) ( this.segmentLength = segmentLength; ) double segmentLength; // Długość linii /** * Zastąpiona metoda klasy obliczająca pole powierzchni linia */ double getSquare( ) ( return 0; ) /** * Przesłonięta metoda klasy obliczająca obwód odcinka */ double getPerimeter() ( return this.segmentLength; ) String getDescription() ( return "Długość segmentu: " + this.segmentLength; ) )

Klasa LineSegment rozszerza punkt

oznacza, że ​​klasa LineSegment dziedziczy po klasie Point. Metody LineSegment::getSquare() i LineSegment::getPerimeter() zastępują odpowiednie metody klasy bazowej. Pole segmentu wynosi zawsze zero, a pole obwodu jest równe długości tego segmentu.

Teraz podobnie jak w klasie segment, opiszemy klasę trójkąt (która również dziedziczy po klasie punktu):

/** * Klasa trójkąta. */ klasa Triangle rozszerza Punkt ( /** * Konstruktor klasy. Jako dane wejściowe przyjmuje trzy parametry: * długość boku A, długość boku B, * kąt pomiędzy tymi bokami (w stopniach) */ Triangle(podwójny bokA, podwójny bokB, double angleAB ) ( this.sideA = sideA; this.sideB = sideB; this.angleAB = angleAB; ) double sideA; //Pole klasy, przechowuje wartość boku A w opisywanym trójkącie double sideB; //Pole klasy, przechowuje wartość boku B w opisywanym trójkącie trójkąt double angleAB; //Pole klasy przechowujące kąt (w stopniach) pomiędzy dwoma bokami opisywanego trójkąta /** * Metoda klasy obliczająca pole trójkąta */ double getSquare() ( double Square = (this.sideA * this.sideB * Math.sin(this.angleAB * Math.PI / 180))/2; return kwadrat; ) /** * Metoda klasy obliczająca obwód trójkąt */ double getPerimeter() ( double sideC = Math.sqrt(Math. pow(this.sideA, 2) + Math.pow(this.sideB, 2) - 2 * this.sideA * this.sideB * Math.cos (this.angleAB * Math.PI / 180)); podwójny obwód = ta.stronaA + ta.stronaB + stronaC; obwód powrotu; ) String getDescription() (zwróć "Trójkąt o bokach: " + this.sideA + ", " + this.sideB + " i kąt pomiędzy nimi: " + this.angleAB; ) )

Nie ma tu nic nowego. Ponadto metody Triangle::getSquare() i Triangle::getPerimeter() zastępują odpowiadające im metody klasy bazowej.
Cóż, teraz właściwie sam kod, który pokazuje magię polimorfizmu i ujawnia moc OOP:

Klasa Main ( /** * Tutaj działa program */ public static void main(String args) ( //ArrayList — Jest to specjalna struktura danych w Javie, // która pozwala na przechowywanie obiektów określonego typu w array.ArrayList figurki = new ArrayList (); //dodaj trzy różne obiekty do tablicy figur figurek.figury.add(new Point()); figurki.add(nowyodcineklinii(133)); figurki.add(nowy trójkąt(10, 17, 55)); for ( int i = 0;i

Stworzyliśmy tablicę obiektów klasy Point, a ponieważ klasy LineSegment i Triangle dziedziczą po klasie Point, możemy je umieścić w tej tablicy. Okazuje się, że każdą figurę znajdującą się w tablicy figurek możemy traktować jako obiekt klasy Point. Na tym właśnie polega polimorfizm: nie wiadomo, do której klasy należą obiekty w tablicy figurek, ale ponieważ wszystkie obiekty w tej tablicy należą do tej samej klasy bazowej Point, to można zastosować także wszystkie metody, które mają zastosowanie do klasy Point do klas potomnych.


Teraz o enkapsulacji. Fakt, że parametry figury oraz metody obliczania pola i obwodu umieściliśmy w jednej klasie, to enkapsulacja; zamknęliśmy figury w oddzielnych klasach. Fakt, że w klasie używamy specjalnej metody do obliczania obwodu, to enkapsulacja; obliczenie obwodu ujęliśmy w metodzie getPerimiter(). Innymi słowy, enkapsulacja ukrywa implementację (być może najkrótsza, a jednocześnie pojemna definicja enkapsulacji).


Pełny przykładowy kod:

Importuj java.util.ArrayList; class Main ( /** * Tutaj uruchamiany jest program */ public static void main(String args) ( //ArrayList to specjalna struktura danych w Javie, // która umożliwia przechowywanie obiektów określonego typu w tablicy. ArrayList figury = new ArrayList (); //dodaj trzy różne obiekty do tablicy figur figury.figury.add(new Point()); figurki.add(newSegmentLinii(133)); figurki.add(nowy Trójkąt(10, 17, 55)); for ( int i = 0;i

Jeśli zauważysz błąd, zaznacz fragment tekstu i naciśnij Ctrl+Enter
UDZIAŁ:
Komputery i nowoczesne gadżety