JavaRush /Blog Java /Random-PL /Konstruktory klasy bazowej

Konstruktory klasy bazowej

Opublikowano w grupie Random-PL
Cześć! Ostatnim razem rozmawialiśmy o konstruktorach i wiele się o nich dowiedzieliśmy. Teraz porozmawiamy o czymś takim jak konstruktory klas bazowych. Co to jest klasa bazowa ? Faktem jest, że w Javie kilka różnych klas może mieć wspólne pochodzenie. Konstruktorzy klasy bazowej - 2Nazywa się to dziedziczeniem . Kilka klas potomków może mieć jedną wspólną klasę przodków. Wyobraźmy sobie na przykład, że mamy klasę Animal(zwierzę):
public class Animal {

   String name;
   int age;
}
Możemy dla niego stworzyć np. 2 klasy potomne - Cati Dog. Odbywa się to za pomocą słowa kluczowego extends.
public class Cat extends Animal {

}

public class Dog extends Animal {

}
Może nam się to przydać w przyszłości. Przykładowo, jeśli zadaniem będzie łapanie myszy, utworzymy w programie obiekt Cat. Jeśli zadaniem jest bieganie za kijem, wówczas korzystamy z obiektu Dog. A jeśli stworzymy program symulujący klinikę weterynaryjną, to będzie on współpracował z klasą Animal(aby móc leczyć zarówno koty, jak i psy). Bardzo ważne jest, aby pamiętać na przyszłość, że podczas tworzenia obiektu najpierw wywoływany jest konstruktor jego klasy bazowej , a dopiero potem konstruktor samej klasy, której obiekt tworzymy. Oznacza to, że podczas tworzenia obiektu Catnajpierw będzie działał konstruktor klasy Animal, a dopiero potem konstruktor Cat. Aby się o tym przekonać, dodajmy do konstruktorów Cati Animalwyprowadźmy na konsolę.
public class Animal {

   public Animal() {
       System.out.println(„Konstruktor zwierząt ukończony”);
   }
}


public class Cat extends Animal {

   public Cat() {
       System.out.println(„Konstruktor Cat zadziałał!”);
   }

   public static void main(String[] args) {
       Cat cat = new Cat();
   }
}
Wyjście konsoli:

Отработал конструктор Animal
Отработал конструктор Cat!
Rzeczywiście, tak to wszystko działa! Po co to jest? Na przykład, aby uniknąć duplikowania wspólnych pól dwóch klas. Na przykład każde zwierzę ma serce i mózg, ale nie każde zwierzę ma ogon. Możemy zadeklarować pola wspólne dla wszystkich zwierząt brainw heartklasie nadrzędnej Animali pole tailw podklasie Cat. Teraz stworzymy konstruktor dla klasy Cat, w którym przekażemy wszystkie 3 pola.
public class Cat extends Animal {

   String tail;

   public Cat(String brain, String heart, String tail) {
       this.brain = brain;
       this.heart = heart;
       this.tail = tail;
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Mózg", "Serce", "Ogon");
   }
}
Zwróć uwagę:konstruktor działa pomyślnie, mimo że klasa Catnie posiada pól braini heart. Pola te zostały „pobrane” z klasy bazowej Animal. Klasa potomna ma dostęp do pól klasy bazowej, dzięki czemu Catsą one widoczne w naszej klasie. Nie musimy zatem Catpowielać tych pól w klasie – możemy je pobrać z klasy Animal. Co więcej, możemy jawnie wywołać konstruktor klasy bazowej w konstruktorze klasy potomnej. Klasa bazowa nazywana jest także „nadklasą i dlatego w Javie używane jest słowo kluczowe super. W poprzednim przykładzie
public Cat(String brain, String heart, String tail) {
       this.brain = brain;
       this.heart = heart;
       this.tail = tail;
   }
Każde pole znajdujące się w naszej klasie nadrzędnej przypisaliśmy osobno. W rzeczywistości nie musisz tego robić. Wystarczy wywołać konstruktor klasy nadrzędnej i przekazać mu niezbędne parametry:
public class Animal {

   String brain;
   String heart;

   public Animal(String brain, String heart) {
       this.brain = brain;
       this.heart = heart;
   }

public class Cat extends Animal {

   String tail;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       this.tail = tail;
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Mózg", "Serce", "Ogon");
   }
}
W konstruktorze Catwywołaliśmy konstruktora Animali przekazaliśmy mu dwa pola. Musimy tylko jawnie zainicjować jedno pole, tailktóre Animalnie jest obecne. Pamiętasz, jak powiedzieliśmy, że podczas tworzenia obiektu najpierw wywoływany jest konstruktor klasy nadrzędnej? Dlatego właśnie słowo super()powinno zawsze znajdować się na pierwszym miejscu w konstruktorze! W przeciwnym razie logika konstruktorów zostanie złamana, a program wygeneruje błąd.
public class Cat extends Animal {

   String tail;

   public Cat(String brain, String heart, String tail) {
       this.tail = tail;
       super(brain, heart);//błąd!
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Mózg", "Serce", "Ogon");
   }
}
Kompilator wie, że podczas tworzenia obiektu klasy potomnej najpierw wywoływany jest konstruktor klasy bazowej. A jeśli spróbujesz ręcznie zmienić to zachowanie, nie pozwoli na to.

Proces tworzenia obiektu.

Powyżej przyjrzeliśmy się przykładowi z klasą bazową i klasą nadrzędną - Animali Cat. Teraz, używając tych dwóch klas jako przykładu, przyjrzymy się procesowi tworzenia obiektu i inicjalizacji zmiennych. Wiemy, że zmienne są statyczne , a zmienne instancji (niestatyczne). Wiemy również, że klasa bazowa Animalma swoje własne zmienne, a klasa potomna Catma swoje własne. AnimalDla przejrzystości dodajmy Catdo klasy jedną zmienną statyczną . Zmienną animalCountklasową Animalbyłaby całkowita liczba gatunków zwierząt na Ziemi, a zmienną catsCountbyłaby liczba gatunków kotów. Dodatkowo przypiszemy wartości początkowe wszystkim zmiennym niestatycznym obu klas (co następnie ulegnie zmianie w konstruktorze).
public class Animal {

   String brain = „Początkowa wartość mózgu w klasie zwierząt”;
   String heart = „Początkowa wartość serca w klasie zwierząt”;

   public static int animalCount = 7700000;

   public Animal(String brain, String heart) {
       System.out.println(„Trwa wykonywanie konstruktora klasy bazowej Animal”);
       System.out.println(„Czy zmienne klasy Animal zostały już zainicjowane?”);
       System.out.println(„Bieżąca wartość zmiennej statycznej animalCount =” + animalCount);
       System.out.println(„Aktualna wartość mózgu w klasie Animal =” + this.brain);
       System.out.println(„Aktualna wartość serca w klasie Animal =” + this.heart);
       System.out.println(„Czy zmienne klasy Cat zostały już zainicjowane?”);
       System.out.println(„Bieżąca wartość zmiennej statycznej kotyCount =” + Cat.catsCount);

       this.brain = brain;
       this.heart = heart;
       System.out.println(„Konstruktor podstawowej klasy zwierząt został ukończony!”);
       System.out.println(„Aktualna wartość mózgu =” + this.brain);
       System.out.println(„Aktualna wartość serca =” + this.heart);
   }
}

public class Cat extends Animal {

   String tail = „Początkowa wartość ogona w klasie Cat”;

   static int catsCount = 37;

   public Cat(String brain, String heart, String tail) {
       super(brain, heart);
       System.out.println(„Konstruktor klasy Cat został uruchomiony (konstruktor Animal został już wykonany)”);
       System.out.println(„Bieżąca wartość zmiennej statycznej kotyCount =” + catsCount);
       System.out.println(„Ogon wartości bieżącej =” + this.tail);
       this.tail = tail;
       System.out.println(„Ogon wartości bieżącej =” + this.tail);
   }

   public static void main(String[] args) {
       Cat cat = new Cat("Mózg", "Serce", "Ogon");
   }
}
Tworzymy więc nowy obiekt klasy Catodziedziczonej z Animal. Dodajmy do naszego programu szczegółowe dane wyjściowe konsoli, aby zobaczyć, co się stanie i w jakiej kolejności. Oto, co zostanie wypisane na konsolę w wyniku utworzenia obiektu Cat:

Выполняется конструктор базового класса Animal
Были ли уже проинициализированы переменные класса Animal?
Текущее oznaczający статической переменной animalCount = 7700000
Текущее oznaczający brain в классе Animal = Изначальное oznaczający brain в классе Animal
Текущее oznaczający heart в классе Animal = Изначальное oznaczający heart в классе Animal
Были ли уже проинициализированы переменные класса Cat?
Текущее oznaczający статической переменной catsCount = 37
Конструктор базового класса Animal завершил работу!
Текущее oznaczający brain = Мозг
Текущее oznaczający heart = Сердце
Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
Текущее oznaczający статической переменной catsCount = 37
Текущее oznaczający tail = Изначальное oznaczający tail в классе Cat
Текущее oznaczający tail = Хвост
Zatem teraz możemy wyraźnie zobaczyć, w jakiej kolejności inicjowane są zmienne i wywoływane konstruktory podczas tworzenia nowego obiektu:
  1. Inicjowane są zmienne statyczne klasy bazowej ( ) Animal. W naszym przypadku zmiennej animalCountklasy Animalprzypisano wartość 7700000.

  2. Inicjowane są zmienne statyczne klasy potomka ( ) Cat. Uwaga - nadal jesteśmy w konstruktorze Animal, a konsola już mówi:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее oznaczający статической переменной animalCount = 7700000
        Текущее oznaczający brain в классе Animal = Изначальное oznaczający brain в классе Animal
        Текущее oznaczający heart в классе Animal = Изначальное oznaczający heart в классе Animal
        Были ли уже проинициализированы переменные класса Cat?
        Текущее oznaczający статической переменной catsCount = 37
  3. Następnie inicjalizowane są zmienne niestatyczne klasy bazowej . Specjalnie przypisaliśmy im wartości początkowe, które następnie są zmieniane w konstruktorze na nowe. Konstruktor Animalnie zakończył jeszcze swojej pracy, ale początkowe wartości brainzostały heartjuż przypisane:

    
        Выполняется конструктор базового класса Animal
        Были ли уже проинициализированы переменные класса Animal?
        Текущее oznaczający статической переменной animalCount = 7700000
        Текущее oznaczający brain в классе Animal = Изначальное oznaczający brain в классе Animal
        Текущее oznaczający heart в классе Animal = Изначальное oznaczający heart в классе Animal
  4. Konstruktor klasy bazowej zaczyna działać .

    Widzieliśmy już, że jest to dopiero czwarty etap: w pierwszych trzech punktach, w momencie rozpoczęcia pracy konstruktora, Animalwielu zmiennym przypisano już wartości.

  5. Inicjowanie niestatycznych pól klasy podrzędnej ( Cat).

    Dzieje się to zanim projektant Catzacznie pracować.

    W momencie rozpoczęcia pracy zmienna tailmiała już wartość:

    
    Конструктор класса Cat начал работу (конструктор Animal уже был выполнен)
    Текущее oznaczający статической переменной catsCount = 37
    Текущее oznaczający tail = Изначальное oznaczający tail в классе Cat
  6. Wywoływany jest konstruktor klasy potomnej Cat

Tak wygląda proces tworzenia obiektu w Javie! Muszę przyznać, że nie jesteśmy wielkimi fanami wkuwania, ale lepiej jest zapamiętać kolejność inicjowania zmiennych i wywoływania konstruktorów i zapamiętywać je na przyszłość . To znacznie zwiększy Twoją wiedzę na temat postępu programu i stanu obiektów w danym momencie. Co więcej, klasy często nie mają bezpośrednich klas nadrzędnych (superklas/klas bazowych). W takim przypadku elementy powiązane z klasą bazową nie zostaną wykonane.
Komentarze
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION