Wróć do informacji o e-podręczniku Wydrukuj Pobierz materiał do PDF Pobierz materiał do EPUB Pobierz materiał do MOBI Zaloguj się, aby dodać do ulubionych Zaloguj się, aby skopiować i edytować materiał Zaloguj się, aby udostępnić materiał Zaloguj się, aby dodać całą stronę do teczki

Metody wirtualne w języku Java

Java jest językiem czysto obiektowym. Dzięki temu realizuje wiele zagadnień oraz standardowych pojęć programowania obiektowego. Jak już wiemy, w kontekście dziedziczenia istotnym pojęciem są metody wirtualne, które mogą być dziedziczone albo nadpisywane w funkcjach pochodnych. Ze względu na swój charakter nie mogą być zatem statyczne. W języku Java ustanowiono, że każda metoda będzie domyślnie wirtualna. Zatem każda metoda niestatyczna może zostać nadpisana lub odziedziczona w klasie pochodnej.

Ciekawostka

Jeśli chcemy utworzyć metodę, której nie można nadpisać w klasie pochodnej, musimy po deklaracji funkcji dopisać słowo kluczowe final.

Istnieje również pojęcie metody czysto wirtualnejmetoda czysto wirtualnametody czysto wirtualnej, czyli takiej, która musi zostać nadpisana w klasie pochodnej. Metody czysto wirtualne z uwagi na swój charakter mogą występować tylko w klasach abstrakcyjnych. W języku Java takie metody poprzedzamy słowem kluczowym abstract, podobnie jak w przypadku klas abstrakcyjnych. Z tego powodu metody czysto wirtualne nazywa się czasem abstrakcyjnymi.

Hermetyzacja w języku Java

W języku Java mamy do dyspozycji trzy standardowe modyfikatory dostępu, o których była mowa w e‑materiale Paradygmaty programowania obiektowegoP1D1ZES2iParadygmaty programowania obiektowego czyli: prywatny (private), publiczny (public) oraz chroniony (protected), a także domyślny, w którym brak słowa kluczowego poprzedzającego element. Domyślnie dostęp do elementu jest publiczny, jednak tylko wewnątrz tego samego pakietu. Pakiety w języku Java nie są jednak częścią tego kursu, zatem będziemy pomijać domyślny modyfikator dostępu.

Polimorfizm w języku Java

Polimorfizm oznacza wielopostaciowość. W programowaniu paradygmat ten oznacza możliwość traktowania danych (np. zmiennych lub obiektów) w różny sposób. Ten sam obiekt może mieć zatem wiele różnych postaci, z których każda może rozszerzać lub modyfikować jego własności. W języku Java zawarto wiele mechanizmów, które pozwalają realizować polimorfizm.

Przykład

W celu obserwacji paradygmatów programowania obiektowego posłużmy się przykładem, w którym utworzymy dwie klasy: abstrakcyjną klasę bazową Owoc oraz klasę pochodną Jablko.

Linia 1. abstract class Owoc otwórz nawias klamrowy. Linia 2. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc. Linia 3. protected double masa średnik. Linia 5. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Owoc. Linia 6. public void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 7. prawy ukośnik prawy ukośnik ugryzienie powoduje zmniejszenie masy owocu. Linia 8. masa minus znak równości 0 kropka 01 średnik. Linia 9. zamknij nawias klamrowy. Linia 10. zamknij nawias klamrowy. Linia 12. class Jablko extends Owoc otwórz nawias klamrowy. Linia 13. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc przecinek które nie występuje. Linia 14. prawy ukośnik prawy ukośnik w klasie pierwotnej. Linia 15. private int liczbaPestek średnik. 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. public 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 23. prawy ukośnik prawy ukośnik przykładowe nadpisanie metody wirtualnej w klasie Owoc. Linia 24. at Override. Linia 25. public void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 26. System kropka out kropka println otwórz nawias okrągły cudzysłów Ugryzienie jablka cudzysłów zamknij nawias okrągły średnik. Linia 28. prawy ukośnik prawy ukośnik ugryzienie jabłka może wiązać się ze. Linia 29. prawy ukośnik prawy ukośnik zjedzeniem pestki z prawdopodobieństwem 10 procent. Linia 30. if otwórz nawias okrągły Math kropka random otwórz nawias okrągły zamknij nawias okrągły otwórz nawias ostrokątny 1 zamknij nawias okrągły otwórz nawias klamrowy. Linia 31. liczbaPestek minus znak równości 1 średnik. Linia 32. zamknij nawias klamrowy. Linia 34. prawy ukośnik prawy ukośnik wywołanie metody bazowej na danym obiekcie. Linia 35. super kropka ugryz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 36. zamknij nawias klamrowy. Linia 38. prawy ukośnik prawy ukośnik publiczny konstruktor. Linia 39. public Jablko otwórz nawias okrągły double masa przecinek int liczbaPestek zamknij nawias okrągły otwórz nawias klamrowy. Linia 40. this kropka masa znak równości masa średnik. Linia 41. this kropka liczbaPestek znak równości liczbaPestek średnik. Linia 42. zamknij nawias klamrowy. Linia 43. zamknij nawias klamrowy.

W języku Java przewidziano rodzaj metadanychmetadanemetadanych, który nazywamy adnotacją. Przykład można zaobserwować w wersie 24. Określenie @Override oznacza, że nadpisujemy metodę z klasy bazowej. Adnotacja ta jest opcjonalna, jednak sprawia, że kod zyskuje na czytelności.

Warto zwrócić uwagę na wers nr 35, w którym użyliśmy konstrukcji super(). Konstrukcja ta powoduje odwołanie do klasy bazowej. Dzięki temu możemy rozszerzać metody, jednocześnie wykorzystując bazowy kod. Takie możliwości są zgodne z paradygmatem polimorfizmu, ponieważ klasa Jablko traktowana jest również jako klasa Owoc. Wywołanie metody super.ugryz() spowoduje przejście do metody ugryz() w klasie Owoc. Wers nr 35 będzie skutkować zatem zmniejszeniem masy obiektu klasy Jablko w taki sam sposób, który zdefiniowano w klasie bazowej. Jednak w przypadku klasy Jablko wiąże się to również z prawdopodobnym zmniejszeniem liczby pestek.

W dalszej części kodu występuje konstruktor. Dzięki ustawieniu widoczności pola masa na protected możemy zmodyfikować je w klasie pochodnej. Gdyby pole to było prywatne, aby zmodyfikować jego wartość, musielibyśmy zdefiniować wirtualny konstruktor w klasie Owoc oraz użyć konstrukcji super(). Wówczas kod mógłby wyglądać w następujący sposób:

Linia 1. abstract class Owoc otwórz nawias klamrowy. Linia 2. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc. Linia 3. private double masa średnik. Linia 5. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Owoc. Linia 6. public void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 7. prawy ukośnik prawy ukośnik ugryzienie powoduje zmniejszenie masy owocu. Linia 8. masa minus znak równości 0 kropka 01 średnik. Linia 9. zamknij nawias klamrowy. Linia 11. prawy ukośnik prawy ukośnik publiczny wirtualny konstruktor. Linia 12. public Owoc otwórz nawias okrągły double masa zamknij nawias okrągły otwórz nawias klamrowy. Linia 13. this kropka masa znak równości masa średnik. Linia 14. zamknij nawias klamrowy. Linia 15. zamknij nawias klamrowy. Linia 17. class Jablko extends Owoc otwórz nawias klamrowy. Linia 18. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc przecinek które nie występuje. Linia 19. prawy ukośnik prawy ukośnik w klasie pierwotnej. Linia 20. private 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. public 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 28. prawy ukośnik prawy ukośnik przykładowe nadpisanie metody wirtualnej w klasie Owoc. Linia 29. at Override. Linia 30. public void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 31. System kropka out kropka println otwórz nawias okrągły cudzysłów Ugryzienie jablka cudzysłów zamknij nawias okrągły średnik. Linia 33. prawy ukośnik prawy ukośnik ugryzienie jabłka może wiązać się ze. Linia 34. prawy ukośnik prawy ukośnik zjedzeniem pestki z prawdopodobieństwem 10 procent. Linia 35. if otwórz nawias okrągły Math kropka random otwórz nawias okrągły zamknij nawias okrągły otwórz nawias ostrokątny 1 zamknij nawias okrągły otwórz nawias klamrowy. Linia 36. liczbaPestek minus znak równości 1 średnik. Linia 37. zamknij nawias klamrowy. Linia 39. prawy ukośnik prawy ukośnik wywołanie metody bazowej na danym obiekcie. Linia 40. super kropka ugryz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 41. zamknij nawias klamrowy. Linia 43. prawy ukośnik prawy ukośnik publiczny konstruktor. Linia 44. public Jablko otwórz nawias okrągły double masa przecinek int liczbaPestek zamknij nawias okrągły otwórz nawias klamrowy. Linia 45. super otwórz nawias okrągły masa zamknij nawias okrągły średnik. Linia 46. this kropka liczbaPestek znak równości liczbaPestek średnik. Linia 47. zamknij nawias klamrowy. Linia 48. zamknij nawias klamrowy.

Niezależnie od wybranego rozwiązania, paradygmat polimorfizmu zawarty w języku Java pozwala nam traktować klasy pochodne również jako klasy bazowe. Dzięki temu, możemy utworzyć instancję klasy Jablko, którą przypiszemy do zmiennej referencyjnej typu Owoc. Taki zabieg spowoduje, że zmienna ta będzie mogła wywoływać jedynie te metody, które są zawarte w klasie Owoc, metody z klasy Jablko zostaną ukryte. Mechanizm ten umożliwia np. stworzenie wielu klas pochodnych klasy Owoc (np. Pomarancza, Arbuz), a następnie przechowywanie ich instancji w jednej tablicy typu Owoc.

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 nowe instancje klasy Jablko. Linia 4. Jablko jablko1 znak równości new Jablko otwórz nawias okrągły 0 kropka 3 przecinek 3 zamknij nawias okrągły średnik. Linia 5. Jablko jablko2 znak równości new Jablko otwórz nawias okrągły 0 kropka 2 przecinek 2 zamknij nawias okrągły średnik. Linia 7. prawy ukośnik prawy ukośnik utworzenie tablicy typu owoc. Linia 8. Owoc otwórz nawias kwadratowy zamknij nawias kwadratowy tablicaOwocow znak równości otwórz nawias klamrowy jablko1 przecinek jablko2 zamknij nawias klamrowy średnik. Linia 10. prawy ukośnik prawy ukośnik dla każdego owocu z tablicyOwocow. Linia 11. for otwórz nawias okrągły Owoc owoc dwukropek tablicaOwocow zamknij nawias okrągły otwórz nawias klamrowy. Linia 12. prawy ukośnik prawy ukośnik poniższa linijka wypisze dwukropek cudzysłów Ugryzienie jablka cudzysłów. Linia 13. owoc kropka ugryz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 14. prawy ukośnik prawy ukośnik poniższa linijka jest niepoprawna. Linia 15. owoc kropka zabierzPestke otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 16. zamknij nawias klamrowy. Linia 17. zamknij nawias klamrowy. Linia 18. zamknij nawias klamrowy.

Warto zaznaczyć, że w wypadku wersu nr 13 zostanie wywołana metoda z klasy pochodnej – z klasy Jablko, ponieważ tylko te owoce zawarliśmy w tablicy.

Wers nr 14 nie jest poprawny, ponieważ nie każda klasa oparta na klasie Owoc musi zawierać metodę zabierzPestke().

Całość kodu, w celu jego przetestowania, wygląda następująco:

Linia 1. abstract class Owoc otwórz nawias klamrowy. Linia 2. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc. Linia 3. private double masa średnik. Linia 5. prawy ukośnik prawy ukośnik przykładowa metoda w klasie Owoc. Linia 6. public void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 7. prawy ukośnik prawy ukośnik ugryzienie powoduje zmniejszenie masy owocu. Linia 8. masa minus znak równości 0 kropka 01 średnik. Linia 9. zamknij nawias klamrowy. Linia 11. prawy ukośnik prawy ukośnik publiczny wirtualny konstruktor. Linia 12. public Owoc otwórz nawias okrągły double masa zamknij nawias okrągły otwórz nawias klamrowy. Linia 13. this kropka masa znak równości masa średnik. Linia 14. zamknij nawias klamrowy. Linia 15. zamknij nawias klamrowy. Linia 17. class Jablko extends Owoc otwórz nawias klamrowy. Linia 18. prawy ukośnik prawy ukośnik przykładowe pole w klasie Owoc przecinek które nie występuje. Linia 19. prawy ukośnik prawy ukośnik w klasie pierwotnej. Linia 20. private 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. public 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 28. prawy ukośnik prawy ukośnik przykładowe nadpisanie metody wirtualnej w klasie Owoc. Linia 29. at Override. Linia 30. public void ugryz otwórz nawias okrągły zamknij nawias okrągły otwórz nawias klamrowy. Linia 31. System kropka out kropka println otwórz nawias okrągły cudzysłów Ugryzienie jablka cudzysłów zamknij nawias okrągły średnik. Linia 33. prawy ukośnik prawy ukośnik ugryzienie jabłka może wiązać się ze. Linia 34. prawy ukośnik prawy ukośnik zjedzeniem pestki z prawdopodobieństwem 10 procent. Linia 35. if otwórz nawias okrągły Math kropka random otwórz nawias okrągły zamknij nawias okrągły otwórz nawias ostrokątny 1 zamknij nawias okrągły otwórz nawias klamrowy. Linia 36. liczbaPestek minus znak równości 1 średnik. Linia 37. zamknij nawias klamrowy. Linia 39. prawy ukośnik prawy ukośnik wywołanie metody bazowej na danym obiekcie. Linia 40. super kropka ugryz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 41. zamknij nawias klamrowy. Linia 43. prawy ukośnik prawy ukośnik publiczny konstruktor. Linia 44. public Jablko otwórz nawias okrągły double masa przecinek int liczbaPestek zamknij nawias okrągły otwórz nawias klamrowy. Linia 45. super otwórz nawias okrągły masa zamknij nawias okrągły średnik. Linia 46. this kropka liczbaPestek znak równości liczbaPestek średnik. Linia 47. zamknij nawias klamrowy. Linia 48. zamknij nawias klamrowy. Linia 50. public class Main otwórz nawias klamrowy. Linia 51. 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 52. prawy ukośnik prawy ukośnik nowe instancje klasy Jablko. Linia 53. Jablko jablko1 znak równości new Jablko otwórz nawias okrągły 0 kropka 3 przecinek 3 zamknij nawias okrągły średnik. Linia 54. Jablko jablko2 znak równości new Jablko otwórz nawias okrągły 0 kropka 2 przecinek 2 zamknij nawias okrągły średnik. Linia 56. prawy ukośnik prawy ukośnik utworzenie tablicy typu owoc. Linia 57. Owoc otwórz nawias kwadratowy zamknij nawias kwadratowy tablicaOwocow znak równości otwórz nawias klamrowy jablko1 przecinek jablko2 zamknij nawias klamrowy średnik. Linia 59. prawy ukośnik prawy ukośnik dla każdego owocu z tablicyOwocow. Linia 60. for otwórz nawias okrągły Owoc owoc dwukropek tablicaOwocow zamknij nawias okrągły otwórz nawias klamrowy. Linia 61. prawy ukośnik prawy ukośnik poniższa linijka wypisze dwukropek cudzysłów Ugryzienie jablka cudzysłów. Linia 62. owoc kropka ugryz otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 63. prawy ukośnik prawy ukośnik poniższa linijka jest niepoprawna. Linia 64. prawy ukośnik prawy ukośnik owoc kropka zabierzPestke otwórz nawias okrągły zamknij nawias okrągły średnik. Linia 65. zamknij nawias klamrowy. Linia 66. zamknij nawias klamrowy. Linia 67. zamknij nawias klamrowy.

Słownik

metadane
metadane

informacje opisujące dane; stosowane są do opisu zasobów informacji oraz obiektów informacji

metoda czysto wirtualna
metoda czysto wirtualna

metoda, która musi zostać nadpisana w klasie pochodnej; może występować tylko w klasie abstrakcyjnej

modyfikatory dostępu
modyfikatory dostępu

słowa kluczowe, dzięki którym definiujemy zakres widoczności elementów takich jak klasy, pola oraz metody