4.1 Dziedziczenie — to łatwe
Dziedziczenie — to fundamentalna koncepcja programowania obiektowego (OOP), która pozwala jednej klasie (nazywanej klasą podrzędną lub subclass) dziedziczyć pola i metody innej klasy (nazywanej klasą nadrzędną lub superclass).
Takie podejście pozwala tworzyć bardziej ogólne klasy i ponownie wykorzystywać kod, poprawiając organizację i utrzymanie kodu.
Dlaczego potrzebne jest dziedziczenie?
Załóżmy, że musisz napisać jakiś kod i zdecydowałeś się zrobić to w formie klasy. Potem dowiedziałeś się, że w twoim projekcie już istnieje klasa, która robi prawie wszystko, czego potrzebujesz, i czego potrzebujesz w swojej klasie. Możesz po prostu skopiować kod tej klasy do swojej i używać go do woli.
Albo możesz „jakby skopiować”. Możesz zadeklarować tę klasę jako rodzic swojej klasy, a wtedy JavaScript doda twojej klasie zachowanie klasy rodzica.
Wyobraź sobie, że jesteś naturą i chcesz stworzyć psa. Co będzie szybsze: stworzyć psa z bakterii w ciągu miliarda lat czy udomowić wilka w ciągu 200 tysięcy lat?
4.2 Koncepcja dziedziczenia przez prototypy
Dziedziczenie przez prototypy w JavaScript — to jeden z podstawowych mechanizmów, który pozwala obiektom dziedziczyć właściwości i metody innych obiektów. Dzięki temu można tworzyć skomplikowane hierarchie obiektów i ponownie wykorzystywać kod.
Każdy obiekt w JavaScript ma ukrytą właściwość [[Prototype]], która wskazuje na jego prototyp. Prototypy są używane do realizacji dziedziczenia, które pozwala obiektom dziedziczyć właściwości i metody od innych obiektów.
Przykład prostego dziedziczenia
Krok 1: Tworzenie bazowego obiektu
const animal = {
eat() {
console.log('Eating...');
},
sleep() {
console.log('Sleeping...');
}
};
Krok 2: Tworzenie obiektu-dziedzica
const dog = Object.create(animal);
dog.bark = function() {
console.log('Barking...');
};
Krok 3: Używanie dziedziczonych właściwości i metod
dog.eat(); // Wyświetli: Eating...
dog.sleep(); // Wyświetli: Sleeping...
dog.bark(); // Wyświetli: Barking...
W tym przykładzie obiekt dog
dziedziczy metody eat()
i sleep()
od obiektu
animal
i dodaje swoją metodę — bark()
.
4.3 Głębokie dziedziczenie przez prototypy
Łańcuch prototypów
W JavaScript dziedziczenie może być bardziej skomplikowane, kiedy obiekty dziedziczą od siebie nawzajem, tworząc łańcuch prototypów.
Przykład łańcucha prototypów
W tym przykładzie obiekt dog
dziedziczy od mammal
, który z kolei dziedziczy od
animal
. To tworzy łańcuch prototypów, gdzie dog
ma dostęp do wszystkich metod
mammal
i animal
.
const animal = {
eat() {
console.log('Eating...');
}
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Walking...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Barking...');
};
dog.eat(); // Wyświetli: Eating...
dog.walk(); // Wyświetli: Walking...
dog.bark(); // Wyświetli: Barking...
Sprawdzanie łańcucha prototypów
Metoda isPrototypeOf()
pozwala sprawdzić, czy obiekt jest prototypem innego obiektu.
Przykład:
console.log(animal.isPrototypeOf(mammal)); // Wyświetli: true
console.log(mammal.isPrototypeOf(dog)); // Wyświetli: true
console.log(animal.isPrototypeOf(dog)); // Wyświetli: true
4.4 Nadpisywanie metod
Dziedziczenie przez prototypy pozwala nie tylko na dodawanie nowych metod, ale także na nadpisywanie istniejących metod.
Przykład nadpisywania metod
W tym przykładzie metoda speak()
w obiekcie dog
nadpisuje metodę speak()
w obiekcie animal
:
const animal = {
speak() {
console.log('Animal speaks');
}
};
const dog = Object.create(animal);
dog.speak = function() {
console.log('Dog barks');
};
animal.speak(); // Wyświetli: Animal speaks
dog.speak(); // Wyświetli: Dog barks
Wywołanie metody obiektu rodzica
Aby wywołać metodę obiektu rodzica w JavaScript możemy użyć metody call()
lub apply()
.
Przykład:
const animal = {
speak() {
console.log('Animal speaks');
}
};
const dog = Object.create(animal);
dog.speak = function() {
animal.speak.call(this);
console.log('Dog barks');
};
dog.speak();
// Wyświetli:
// Animal speaks
// Dog barks
4.5 Zaawansowane użycie dziedziczenia prototypowego
Rozszerzanie wbudowanych obiektów
Możesz rozszerzać wbudowane obiekty JavaScript, dodając metody do ich prototypów.
Przykład:
Array.prototype.sum = function() {
return this.reduce((acc, value) => acc + value, 0);
};
const numbers = [1, 2, 3, 4, 5];
console.log(numbers.sum()); // Wyświetli: 15
Tworzenie wielopoziomowych hierarchii
Możesz tworzyć bardziej złożone wielopoziomowe hierarchie obiektów z pomocą dziedziczenia prototypowego.
Przykład:
const livingBeing = {
breathe() {
console.log('Breathing...');
}
};
const animal = Object.create(livingBeing);
animal.eat = function() {
console.log('Eating...');
};
const mammal = Object.create(animal);
mammal.walk = function() {
console.log('Walking...');
};
const dog = Object.create(mammal);
dog.bark = function() {
console.log('Barking...');
};
dog.breathe(); // Wyświetli: Breathing...
dog.eat(); // Wyświetli: Eating...
dog.walk(); // Wyświetli: Walking...
dog.bark(); // Wyświetli: Barking...
GO TO FULL VERSION