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.
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 :)
Zasady OOP:
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 ”.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.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ędnejAuto
. 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 Employee
ustawimy 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 socialInsuranceNumber
int taxNumber
Model
String height
String hair
String 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 (private
itp public
.) i metody pobierające. Jeśli pole age
klasy Cat
nie jest hermetyzowane, każdy może napisać:
Cat.age = -1000;
A mechanizm enkapsulacji pozwala zabezpieczyć pole age
metodą 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ęAnimal
z jedną metodą - voice()
i dwoma jej potomkami - Cat
i 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 Animal
i 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 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 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 shear
zaró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 AnimalBarbershop
działa z typami Cat
tak, Dog
jakby były tego samego typu. Jednocześnie zachowują się Cat
inaczej Dog
: inaczej używają głosu.
GO TO FULL VERSION