Sekcja „Film samouczek” wprowadza w temat programowania obiektowego w języku Java. Materiał filmowy wyjaśnia pojęcia klasy oraz dziedziczenia. W tej sekcji utrwalimy przyswojone informacje.
Zgodnie z założeniem programowania obiektowego klasa jest modelem, który określa typ oraz zachowanie pewnego zbioru danych – obiektu. Obiekt zwany jest instancjąinstancja klasyinstancją klasy. W uproszczeniu można powiedzieć, że klasa jest typem, a obiekt zmienną.
W przypadku typów prostych – int, double , boolean – nie martwimy się ich implementacją, ponieważ zostały nam dostarczone wraz ze środowiskiem programistycznym. W programowaniu obiektowym mamy możliwość samodzielnego tworzenia typów, dzięki czemu idealnie wpasowują się one w nasze potrzeby.
Definicja klasy może zawierać zarówno pola, które stanowią stan obiektu, jak i funkcje (zwane metodami), które określają zachowanie danego obiektu.
Struktura programu obiektowego w języku Java
Program w języku Java rozpoczynamy od definicji klasy. Może ona przyjmować różne nazwy. Niektórzy klasę główną nazywają tak jak swój program, inni wolą nazwać tę klasę: Main. Dobrą praktyką jest rozpoczynanie nazwy klasy wielką literą. Wewnątrz niej wpisujemy definicję publicznej statycznej funkcji typu void o nazwie main. Typowy program w języku Java zawsze przyjmuje podaną strukturę.
Linia 1. public class Main otwórz nawias klamrowy.
Linia 2. public static void main otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy args zamknij nawias okrągły otwórz nawias klamrowy.
Linia 3. prawy ukośnik prawy ukośnik w tym miejscu zaczynamy pisać nasz program.
Linia 4. zamknij nawias klamrowy.
Linia 5. zamknij nawias klamrowy.
Programując w ten sposób, masz już podstawy programowania obiektowego. Wiesz, co oznaczają poszczególne słowa w tej strukturze?
Zacznijmy od linijki nr 1. Znajdują się w niej dwa słowa kluczowe: public oraz class. W połączeniu z nazwą Main stanowią one definicję klasy publicznej. W języku Java określamy w ten sposób klasę, którą można użyć w dowolnym miejscu programu. Związane jest z nią pojęcie hermetyzacjihermetyzacjahermetyzacji, które zostanie omówione w kolejnych e‑materiałach. W tym momencie możemy przyjąć, że słowo to jest zbędne – jego usunięcie nie zmieni działania programu. Java jest językiem ściśle obiektowym, w którym nawet funkcja rozpoczynająca wykonywanie programu musi być zadeklarowana w klasie.
Przechodzimy do linijki nr 2. Widzimy bardzo charakterystyczną dla języka Java definicję funkcji main – metody, która uruchamiana jest w trakcie startu programu. W momencie kompilacji we wszystkich plikach programu szukana jest właśnie taka definicja. Nie jest określone, w jakiej klasie powinna być zadeklarowana, jednak jest niezbędna do uruchomienia programu.
Wspomniane wcześniej słowo kluczowe public oznacza, że dostęp do metody main jest powszechny – można ją wywołać w dowolnym miejscu programu, w którym posiadamy dostęp do jej klasy. W tym wypadku również klasa ma ustawiony powszechny dostęp, zatem wywołanie funkcji main byłoby możliwe w dowolnym momencie działania programu. Należy jednak pamiętać, że program nie powinien wywoływać sam siebie bez wyraźnej przyczyny, zatem nie należy na przykład wywoływać funkcji main z poziomu funkcji main.
Słowo kluczowe static oznacza, że funkcja main jest statycznametoda statycznastatyczna. W przypadku funkcji głównej programu nie należy przejmować się jej statycznością. Jak wspomnieliśmy wcześniej, najprawdopodobniej nie będziemy chcieli jej wywoływać. Nie zmienia to faktu, że słowo static jest niezbędne do uruchomienia programu.
Słowo kluczowe void oznacza, że metoda main jest tak naprawdę procedurą – nie zwraca żadnej wartości. W wielu językach uznano, że funkcja główna programu powinna zwracać status, tj. informację czy wszystkie operacje zakończyły się poprawnie, jako typ integer. Jednak nie dotyczy to języka Java, w którym nie musimy zwracać statusu programu.
Ostatnią charakterystyczną cechą linijki nr 2 są przyjmowane parametry. Widzimy, że metoda przyjmuje tablicę łańcuchów znaków – String. Są to parametry wywołania programu, które mogą pochodzić z systemu operacyjnego lub jego wywołania – np. z poziomu konsoli. Jedynym, co możemy zmienić w drugiej linijce, aby nadal pozostała ona definicją funkcji głównej programu, jest właśnie nazwa tych parametrów.
Dziedziczenie w języku Java
Dziedziczenie to mechanizm współdzielenia pól oraz metod. W programowaniu obiektowym typy mogą pochodzić od innych typów. Klasy pochodne mogą zarówno dziedziczyć, jak i nadpisywać metody klasy, od której pochodzą. Można wyróżnić m.in. klasy właściwe (czyli takie, które mogą być instancjonowane) oraz klasy abstrakcyjne, które stanowią bazę dla klas pochodnych i nie można utworzyć ich instancji. Instancjonowaniem nazywamy tworzenie obiektów danej klasy. Zasada dziedziczenia stanowi zatem również wzór projektowy, dzięki któremu wspólna praca wielu programistów nad tym samym kodem jest łatwiejsza.
Klasa abstrakcyjna w języku Java może zostać utworzona przez słowo kluczowe abstract.
Linia 1. abstract class Owoc otwórz nawias klamrowy.
Linia 2. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 4. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc.
Linia 5. double masa średnik.
Linia 7. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Owoc.
Linia 8. void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 9. prawy ukośnik prawy ukośnik ugryzienie powoduje zmniejszenie masy owocu.
Linia 10. masa minus znak równości 0 kropka 01 średnik.
Linia 11. zamknij nawias klamrowy.
Linia 12. zamknij nawias klamrowy.
Klasa Owoc została zaimplementowana jako abstrakcyjna, ponieważ definiuje ona tylko ogólną kategorię, jaką są owoce. Definicja ta powinna zostać jednak doprecyzowana, żeby mogła faktycznie zaistnieć. Gdybyśmy pozwolili na utworzenie instancji klasy Owoc, nie wiedzielibyśmy, jaki to owoc. Zaimplementujmy zatem klasę pochodną, która powie nam więcej o wybranym owocu. W języku Java klasę pochodną możemy utworzyć poprzez następującą konstrukcję:
Linia 1. class Jablko extends Owoc otwórz nawias klamrowy.
Linia 2. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 3. prawy ukośnik prawy ukośnik klasy pochodnej.
Linia 5. prawy ukośnik prawy ukośnik przykładowe pole w klasie Jablko przecinek które nie występuje.
Linia 6. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 7. int liczbaPestek średnik.
Linia 9. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Jablko przecinek która nie występuje.
Linia 10. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 11. void zabierzPestke otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 12. liczbaPestek minus minus średnik.
Linia 13. zamknij nawias klamrowy.
Linia 14. zamknij nawias klamrowy.
Zauważ, że w przypadku klasy Jablko nie mamy już do czynienia z klasą abstrakcyjną, zatem możemy utworzyć jej instancję. Sama definicja klasy Jablko nie może istnieć samodzielnie, ponieważ odnosi się do definicji klasy abstrakcyjnej Owoc. Zwróć uwagę, że w klasie pochodnej nie musimy zawierać informacji o polach oraz metodach, które już występują w klasie bazowej.
Aby zaobserwować mechanizm dziedziczenia oraz potwierdzić fakt, że w klasie Jablko istnieją pola oraz metody z klasy bazowej Owoc, a także pola i metody dodane w definicji klasy pochodnej, możemy napisać prosty program wykorzystujący utworzone klasy.
Linia 1. abstract class Owoc otwórz nawias klamrowy.
Linia 2. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 4. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc.
Linia 5. double masa średnik.
Linia 7. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Owoc.
Linia 8. void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 9. prawy ukośnik prawy ukośnik ugryzienie powoduje zmniejszenie masy owocu.
Linia 10. masa minus znak równości 0 kropka 01 średnik.
Linia 11. zamknij nawias klamrowy.
Linia 12. zamknij nawias klamrowy.
Linia 14. class Jablko extends Owoc otwórz nawias klamrowy.
Linia 15. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 16. prawy ukośnik prawy ukośnik klasy pochodnej.
Linia 18. prawy ukośnik prawy ukośnik przykładowe pole w klasie Jablko przecinek które nie występuje.
Linia 19. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 20. int liczbaPestek średnik.
Linia 22. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Jablko przecinek która nie występuje.
Linia 23. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 24. void zabierzPestke otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 25. liczbaPestek minus minus średnik.
Linia 26. zamknij nawias klamrowy.
Linia 27. zamknij nawias klamrowy.
Linia 29. public class Main otwórz nawias klamrowy.
Linia 30. public static void main otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy args zamknij nawias okrągły otwórz nawias klamrowy.
Linia 31. prawy ukośnik prawy ukośnik nowa instancja klasy Jablko.
Linia 32. Jablko jablko znak równości new Jablko otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 34. prawy ukośnik prawy ukośnik ustawienie wartości masa oraz liczbaPestek.
Linia 35. prawy ukośnik prawy ukośnik instancji klasy Jablko.
Linia 36. jablko kropka masa znak równości 0 kropka 3 średnik.
Linia 37. jablko kropka liczbaPestek znak równości 3 średnik.
Linia 39. prawy ukośnik prawy ukośnik wywołanie metod klasy Jablko.
Linia 40. jablko kropka ugryz otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 41. jablko kropka zabierzPestke otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 43. prawy ukośnik prawy ukośnik poniższa linijka powinna wypisać dwukropek 0 kropka 29 2.
Linia 44. System kropka out kropka println otwórz nawias okrągły jablko kropka masa plus cudzysłów cudzysłów plus jablko kropka liczbaPestek zamknij nawias okrągły średnik.
Linia 45. zamknij nawias klamrowy.
Linia 46. zamknij nawias klamrowy.
Konstruktory
W omawianym dotychczas programie, jeśli chcemy przypisać wartość atrybutów obiektów klasy Jablko, odwołujemy się bezpośrednio do atrybutów obiektu po znaku kropki. Istnieje jednak specjalny rodzaj funkcji, który pozwala na przypisanie wartości atrybutom obiektów podczas ich tworzenia. Nazywamy go konstruktorem. Prześledźmy definicję konstruktora na przykładzie klasy Jablko:
Linia 1. class Jablko extends Owoc otwórz nawias klamrowy.
Linia 2. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 3. prawy ukośnik prawy ukośnik klasy pochodnej.
Linia 5. prawy ukośnik prawy ukośnik przykładowe pole w klasie Jablko przecinek które nie występuje.
Linia 6. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 7. int liczbaPestek średnik.
Linia 9. prawy ukośnik prawy ukośnik konstruktor.
Linia 10. Jablko otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 11. prawy ukośnik prawy ukośnik funkcja ta zostanie wywołana przy tworzeniu obiektu.
Linia 12. prawy ukośnik prawy ukośnik klasy Jablko.
Linia 13. prawy ukośnik prawy ukośnik w tym miejscu możemy przypisywać wartości atrybutom.
Linia 14. prawy ukośnik prawy ukośnik oraz wywoływać metody.
Linia 15. zamknij nawias klamrowy.
Linia 17. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Jablko przecinek która nie występuje.
Linia 18. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 19. void zabierzPestke otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 20. liczbaPestek minus minus średnik.
Linia 21. zamknij nawias klamrowy.
Linia 22. zamknij nawias klamrowy.
W definicji konstruktora możemy zawrzeć także parametry przekazywane tak jak w przypadku zwykłej funkcji:
Linia 1. class Jablko extends Owoc otwórz nawias klamrowy.
Linia 2. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 3. prawy ukośnik prawy ukośnik klasy pochodnej.
Linia 5. prawy ukośnik prawy ukośnik przykładowe pole w klasie Jablko przecinek które nie występuje.
Linia 6. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 7. int liczbaPestek średnik.
Linia 9. prawy ukośnik prawy ukośnik konstruktor.
Linia 10. Jablko otwórz nawias okrągły double masa przecinek int liczbaPestek zamknij nawias okrągły otwórz nawias klamrowy.
Linia 11. prawy ukośnik prawy ukośnik funkcja ta zostanie wywołana przy tworzeniu obiektu.
Linia 12. prawy ukośnik prawy ukośnik klasy Jablko.
Linia 13. prawy ukośnik prawy ukośnik w tym miejscu możemy przypisywać wartości atrybutom.
Linia 14. prawy ukośnik prawy ukośnik oraz wywoływać metody.
Linia 15. zamknij nawias klamrowy.
Linia 17. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Jablko przecinek która nie występuje.
Linia 18. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 19. void zabierzPestke otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 20. liczbaPestek minus minus średnik.
Linia 21. zamknij nawias klamrowy.
Linia 22. zamknij nawias klamrowy.
Przypisujemy przekazane do konstruktora wartości do atrybutów. Jeżeli przesłoniliśmy nazwę atrybutu w konstruktorze (lub innej metodzie), dostęp do atrybutu gwarantuje nam konstrukcja this.
Linia 1. class Jablko extends Owoc otwórz nawias klamrowy.
Linia 2. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 3. prawy ukośnik prawy ukośnik klasy pochodnej.
Linia 5. prawy ukośnik prawy ukośnik przykładowe pole w klasie Jablko przecinek które nie występuje.
Linia 6. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 7. int liczbaPestek średnik.
Linia 9. prawy ukośnik prawy ukośnik konstruktor.
Linia 10. Jablko otwórz nawias okrągły double masa przecinek int liczbaPestek zamknij nawias okrągły otwórz nawias klamrowy.
Linia 11. prawy ukośnik prawy ukośnik funkcja ta zostanie wywołana przy tworzeniu obiektu.
Linia 12. prawy ukośnik prawy ukośnik klasy Jablko.
Linia 13. prawy ukośnik prawy ukośnik w tym miejscu możemy przypisywać wartości atrybutom.
Linia 14. prawy ukośnik prawy ukośnik oraz wywoływać metody.
Linia 16. prawy ukośnik prawy ukośnik przypisanie wartości atrybutu z klasy bazowej.
Linia 17. this kropka masa znak równości masa średnik.
Linia 18. prawy ukośnik prawy ukośnik przypisanie wartości atrybutu z klasy pochodnej.
Linia 19. this kropka liczbaPestek znak równości liczbaPestek średnik.
Linia 20. zamknij nawias klamrowy.
Linia 22. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Jablko przecinek która nie występuje.
Linia 23. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 24. void zabierzPestke otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 25. liczbaPestek minus minus średnik.
Linia 26. zamknij nawias klamrowy.
Linia 27. zamknij nawias klamrowy.
Tak zdefiniowaną klasę możemy instancjonować w następujący sposób:
Linia 1. Jablko jablko znak równości Jablko otwórz nawias okrągły 0 kropka 3 przecinek 3 zamknij nawias okrągły średnik.
Analizowany program,wzbogacony o wykorzystanie konstruktora, prezentuje się następująco:
Linia 1. abstract class Owoc otwórz nawias klamrowy.
Linia 2. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 4. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc.
Linia 5. double masa średnik.
Linia 7. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Owoc.
Linia 8. void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 9. prawy ukośnik prawy ukośnik ugryzienie powoduje zmniejszenie masy owocu.
Linia 10. masa minus znak równości 0 kropka 01 średnik.
Linia 11. zamknij nawias klamrowy.
Linia 12. zamknij nawias klamrowy.
Linia 14. class Jablko extends Owoc otwórz nawias klamrowy.
Linia 15. prawy ukośnik prawy ukośnik w tym miejscu możemy deklarować pola oraz metody.
Linia 16. prawy ukośnik prawy ukośnik klasy pochodnej.
Linia 18. prawy ukośnik prawy ukośnik przykładowe pole w klasie Jablko przecinek które nie występuje.
Linia 19. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 20. int liczbaPestek średnik.
Linia 22. prawy ukośnik prawy ukośnik konstruktor.
Linia 23. Jablko otwórz nawias okrągły double masa przecinek int liczbaPestek zamknij nawias okrągły otwórz nawias klamrowy.
Linia 24. prawy ukośnik prawy ukośnik funkcja ta zostanie wywołana przy tworzeniu obiektu.
Linia 25. prawy ukośnik prawy ukośnik klasy Jablko.
Linia 26. prawy ukośnik prawy ukośnik w tym miejscu możemy przypisywać wartości atrybutom.
Linia 27. prawy ukośnik prawy ukośnik oraz wywoływać metody.
Linia 29. prawy ukośnik prawy ukośnik przypisanie wartości atrybutu z klasy bazowej.
Linia 30. this kropka masa znak równości masa średnik.
Linia 31. prawy ukośnik prawy ukośnik przypisanie wartości atrybutu z klasy pochodnej.
Linia 32. this kropka liczbaPestek znak równości liczbaPestek średnik.
Linia 33. zamknij nawias klamrowy.
Linia 35. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Jablko przecinek która nie występuje.
Linia 36. prawy ukośnik prawy ukośnik w klasie pierwotnej.
Linia 37. void zabierzPestke otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy.
Linia 38. liczbaPestek minus minus średnik.
Linia 39. zamknij nawias klamrowy.
Linia 40. zamknij nawias klamrowy.
Linia 42. public class Main otwórz nawias klamrowy.
Linia 43. public static void main otwórz nawias okrągły String otwórz nawias kwadratowy zamknij nawias kwadratowy args zamknij nawias okrągły otwórz nawias klamrowy.
Linia 44. prawy ukośnik prawy ukośnik nowa instancja klasy Jablko z ustawieniem atrybutów.
Linia 45. prawy ukośnik prawy ukośnik masa znak równości 0 kropka 3 oraz liczbaPestek znak równości 3.
Linia 46. Jablko jablko znak równości new Jablko otwórz nawias okrągły 0 kropka 3 przecinek 3 zamknij nawias okrągły średnik.
Linia 48. prawy ukośnik prawy ukośnik wywołanie metod klasy Jablko.
Linia 49. jablko kropka ugryz otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 50. jablko kropka zabierzPestke otwórz nawias okrągły zamknij nawias okrągły średnik.
Linia 52. prawy ukośnik prawy ukośnik poniższa linijka powinna wypisać dwukropek 0 kropka 29 2.
Linia 53. System kropka out kropka println otwórz nawias okrągły jablko kropka masa plus cudzysłów cudzysłów plus jablko kropka liczbaPestek zamknij nawias okrągły średnik.
Linia 54. zamknij nawias klamrowy.
Linia 55. zamknij nawias klamrowy.
Słownik
hermetyzacja
hermetyzacja
paradygmat programowania obiektowego, który pozwala na zarządzanie dostępem do atrybutów oraz metod w klasie
instancja klasy
instancja klasy
niezależna od innych instancji realizacja modelu danej klasy; stanowi utworzony w pamięci RAM element danych, podczas gdy klasa jest definicją, zgodnie z którą instancja jest tworzona
metoda statyczna
metoda statyczna
metoda wspólna dla wszystkich instancji danej klasy, może być wywołana również wówczas, gdy nie istnieje żadna instancja danej klasy; metody statyczne nie mogą modyfikować żadnych pól niestatycznych klasy