Zasady OOP

Opublikowano w grupie Random-PL
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 wymyślono i wysunięto na pierwszy plan pojęcie „przedmiotu”? 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.

Zasady OOP:

  1. Dziedzictwo
  2. Abstrakcja
  3. Kapsułkowanie
  4. Wielopostaciowość

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. Pierwszy taki język nazywał się Simula i został wynaleziony w latach 60. XX wieku w Norwegii. Simula wprowadziła między innymi pojęcia „ klasa ” i „ metoda ”. Zasady programowania obiektowego - 2
Kristen Nygaard i Ole Johan Dahl – twórcy Simuli
Wydawać by się mogło, że Simula jest językiem starożytnym według standardów programowania, jednak ich „rodzinne” powiązanie z Javą jest widoczne gołym okiem. Najprawdopodobniej możesz łatwo przeczytać zapisany na nim kod i ogólnie wyjaśnić, co robi :)
Begin
  Class Rectangle (Width, Height); Real Width, Height;

   Begin
      Real Area, Perimeter;

      Procedure Update;
      Begin
        Area := Width * Height;
              OutText("Rectangle is updating, Area = "); OutFix(Area,2,8); OutImage;
        Perimeter := 2*(Width + Height);
              OutText("Rectangle is updating, Perimeter = "); OutFix(Perimeter,2,8); OutImage;
      End of Update;

      Update;
      OutText("Rectangle created: "); OutFix(Width,2,6);
      OutFix(Height,2,6); OutImage;
   End of Rectangle;

       Rectangle Class ColouredRectangle (Color); Text Color;

  Begin
      OutText("ColouredRectangle created, color = "); OutText(Color);
      OutImage;
        End of ColouredRectangle;


         Ref(Rectangle) Cr;
   Cr :- New ColouredRectangle(10, 20, "Green");
End;
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 - programowania obiektowego. Wikipedia podaje następującą definicję OOP: Programowanie zorientowane obiektowo (OOP) to 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 obce :) Obecnie OOP jest najpopularniejszą metodologią programowania. Oprócz języka Java zasady OOP są stosowane 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. Zasady programowania obiektowego - 3

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ąć. Dziedziczenie to mechanizm pozwalający opisać nową klasę 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 Auto. 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 uwypuklenie 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 pracownicze, napisaliśmy klasę Employee. Jakie cechy są istotne przy ich opisie w aktach firmy? Imię i nazwisko, data urodzenia, numer PESEL, numer identyfikacji podatkowej. 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 Employeeustawimy zmienne String name, i int age, a informacje dla nas niepotrzebne, takie jak kolor oczu, porzucimy i wyabstrahujemy. Jeśli jednak stworzymy dla agencji katalog fotomodelek, sytuacja zmieni się diametralnie. Aby opisać modelkę, bardzo ważny jest dla nas wzrost, kolor oczu i kolor włosów, ale numer NIP nie jest nam potrzebny. Dlatego w klasie tworzymy zmienne , , . int socialInsuranceNumberint taxNumberModelString heightString hairString eyes

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 ( privateitp public.) i metody pobierające. Jeśli pole ageklasy Catnie jest hermetyzowane, każdy może napisać:
Cat.age = -1000;
A mechanizm enkapsulacji pozwala zabezpieczyć pole agemetodą ustawiającą, w której możemy sprawdzić, czy wiek nie może być liczbą ujemną.

Zasada 4. Polimorfizm

Polimorfizm to zdolność do traktowania wielu typów 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ę Animalz jedną metodą - voice()i dwoma jej potomkami - Cati Dog.
public class Animal {

   public void voice() {

       System.out.println("Głos!");
   }
}

public class Dog extends Animal {


   @Override
   public void voice() {
       System.out.println("Łuk-wow!");
   }
}

public class Cat extends Animal {

   @Override
   public void voice() {
       System.out.println("Miauczeć!");
   }
}
Spróbujmy teraz utworzyć łącze Animali przypisać mu obiekt Dog.
public class Main {

   public static void main(String[] args) {

       Animal dog = new Dog();
       dog.voice();
   }
}
Jak myślisz, która metoda zostanie wywołana? Animal.voice()Lub Dog.voice()? Metoda klasy będzie nosiła nazwę Dog: Hau-woof! Stworzyliśmy referencję Animal, ale obiekt zachowuje się jak Dog. W razie potrzeby może zachowywać się jak kot, koń lub inne zwierzę. Najważniejsze jest przypisanie referencji typu ogólnego Animaldo 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 komunikat „Miau!” 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 salon fryzjerski musi mieć możliwość strzyżenia wszystkich zwierząt, dlatego stworzymy metodę shear()(„strzyżenie”) z parametrem Animal– zwierzę, które będziemy strzyżyć.
public class AnimalBarbershop {

   public void shear(Animal animal) {

       System.out.println(„Fryzura jest gotowa!”);
   }
}
A teraz możemy przekazać do metody shearzarówno obiekty Cat, jak i obiekty Dog!
public static void main(String[] args) {

   Cat cat = new Cat();
   Dog dog = new Dog();

   AnimalBarbershop barbershop = new AnimalBarbershop();

   barbershop.shear(cat);
   barbershop.shear(dog);
}
Oto wyraźny przykład: klasa AnimalBarbershopdziała z typami Cattak, Dogjakby były tego samego typu. Jednocześnie zachowują się Catinaczej Dog: inaczej używają głosu.

Przyczyny pojawienia się OOP

Dlaczego w ogóle powstała ta nowa koncepcja programowania – OOP ? Programiści mieli skuteczne narzędzia: 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 może brzmieć jak „zaimplementuj 7 różnych zakończeń dla gry STALKER w zależności od decyzji, jakie użytkownik podjął w momentach gry A, B, C, D , E, F oraz kombinacje tych rozwiązań.” 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 Game, klasy Stalker, klasy Ending, klasy decyzji gracza, klasy Game Moment 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.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION