Mamy 1 sierpnia. Podjąłem taką decyzję, że teraz będzie premierowy artykuł co trzy dni. Osiągnąłem absolutne minimum w kwestii ilości wpisów na stronie dotyczących programowania, zatem teraz będą tylko "dokładki". Sięgamy do Javy raz kolejny i dzisiaj zaprezentuję Wam jak konstruktor klasy bazowej zdradza przebieg wykonywania czynności mających na celu utworzenie instancji danej klasy. Zatem będzie raczej eksperyment niż przedstawienie czegoś nowego. Mimo wszystko, wytrwajcie do końca. Warto to wiedzieć.

KONSTRUKTOR KLASY BAZOWEJ W JAVA ZAWSZE IDZIE WYŻEJ

Omawialiśmy sobie już dokładnie konstruktory, jak również ich przeciążanie. O dziedziczeniu też już była solidna pogawędka więc zakładam, że to wszystko jest przeczytane. Dotychczas krążyliśmy wokół tych tematów od strony kodowej, czyli jak to prawidłowo rozumieć i napisać. Teraz spojrzymy na to z drugiej strony czyli co się dzieje i w jakiej kolejności podczas tworzenia obiektu przez konstruktory.

W poprzednim artykule była mowa o stercie i jak się zachowują na niej wywołania metod. Konstruktor klasy bazowej będzie doskonałym zobrazowaniem tego w praktyce, abyście rozumieli jak to wszystko jest ze sobą powiązane. Przy okazji mam dla Was konkretne pytanie: czy klasa abstrakcyjna RÓWNIEŻ powinna mieć konstruktor, skoro nigdy nie będzie można utworzyć jej kopii? Chwila namysłu, a ja dorzucam kolejny przykład kodu źródłowego celem demonstracji meritum sprawy:

  • KLASA "Main"
public class Main
{
	public static void main(String[] args)
	{
		new Launcher();
	}
}
  • KLASA "Person"
public abstract class Person
{
	private int age;
	private String name;

	public Person(int age, String name)
	{
		System.out.println("Wywołuję konstruktor klasy bazowej \"Person\"!");

		this.age = age;
		this.name = name;
	}
}
  • KLASA "Programmer"
public abstract class Programmer extends Person
{
	private String language;

	public Programmer(int age, String name, String language)
	{
		super(age, name);
		System.out.println("Wywołuję konstruktor klasy potomnej \"Hacker\"!");

		this.language = language;
	}
}
  • KLASA "FrontEndDeveloper"
public class FrontEndDeveloper extends Programmer
{
	public FrontEndDeveloper(int age, String name, String language)
	{
		super(age, name, language);
		System.out.println("Wywołuję konstruktor klasy potomnej \"FrontEndDeveloper\"!");
	}
}

Uruchomcie program i patrzcie uważnie na konsolę! Co dostrzegacie? Może to, że wbrew pozorom wywołania konstruktorów idą one od samego szczytu dziedziczenia zgodnie z osadzaniem wywołań metod na stosie i konstruktor klasy bazowej jest wykonywany jako pierwszy? Może to, że klasa abstrakcyjna ma prawo mieć "u siebie" konstruktor mimo tego, iż nie można na jej podstawie tworzyć obiektów?

To jest najważniejszy punkt niniejszego wpisu! Chciałem pokazać Wam prawdziwą kolejność wywoływania coraz to bardziej ogólnych konstruktorów. Tak na marginesie jeszcze dopiszę, że ten "łańcuch" wywołań nie kończy się na naszej klasie "najbardziej ogólnej", tylko na "ukrytej" klasie "Object", "matce" wszystkich obiektów. W chwili tworzenia własnej klasy, wykonywane jest niejawne rozszerzanie o klasę "Object", tak samo jakbyśmy dopisali "extends Object" (jeśli nie rozszerzamy jawnie o inną klasę).


Taka ciekawostka. Na tym kończę i dziękuję za pełne przeczytanie! Od tej pory będziecie wiedzieli jak bardzo konstruktor klasy bazowej umieszczony na stosie wywołań metod może przeczyć wstępnemu rozumowaniu. Chociaż...czy tylko tutaj prawda potrafi być zaskakująca?

PODOBNE ARTYKUŁY