Java Inheritance onder de knie: Subclassing en Superclass Principes
Wat is Inheritance?
Inheritance (overerving) kan worden gedefinieerd als het proces waarbij een klasse de eigenschappen (methodes en velden) van een andere klasse verwervt. Met inheritance wordt de informatie op een hiërarchische manier beheersbaar.
De klasse die de eigenschappen van een andere overneemt, heet de subclass (afgeleide klasse, kindklasse) en de klasse wiens eigenschappen worden overgeërfd, heet de superclass (basisklasse, ouderklasse).
Het extends-sleutelwoord
extends is het sleutelwoord dat wordt gebruikt om de eigenschappen van een klasse te overerven. Hier is de syntaxis:
class Super {
.....
.....
}
class Sub extends Super {
.....
.....
}
Voorbeeldcode
Hier is een voorbeeld dat Java inheritance demonstreert. We hebben twee klassen: Calculation en My_Calculation.
Met het extends-sleutelwoord overneemt My_Calculation de methodes addition() en Subtraction() van de Calculation-klasse.
class Calculation {
int z;
public void addition(int x, int y) {
z = x + y;
System.out.println("De som van de gegeven getallen: " + z);
}
public void Subtraction(int x, int y) {
z = x - y;
System.out.println("Het verschil tussen de gegeven getallen: " + z);
}
}
public class My_Calculation extends Calculation {
public void multiplication(int x, int y) {
z = x * y;
System.out.println("Het product van de gegeven getallen: " + z);
}
public static void main(String args[]) {
int a = 20, b = 10;
My_Calculation demo = new My_Calculation();
demo.addition(a, b);
demo.Subtraction(a, b);
demo.multiplication(a, b);
}
}
Compileer en voer uit:
javac My_Calculation.java java My_Calculation
Resultaat:
De som van de gegeven getallen: 30 Het verschil tussen de gegeven getallen: 10 Het product van de gegeven getallen: 200
In het gegeven programma, wanneer een object van de My_Calculation-klasse wordt gemaakt, wordt een kopie van de inhoud van de superclass daarin gemaakt. Daarom kun je met het object van de subclass de leden van de superclass benaderen.
Een superclass-referentievariabele kan een subclass-object bevatten, maar met die variabele kun je alleen de leden van de superclass benaderen. Om de leden van beide klassen te benaderen, is het raadzaam om altijd een referentievariabele naar de subclass te maken.
Als je het bovenstaande programma overweegt, kun je de klasse instantiëren als:
Calculation demo = new My_Calculation(); demo.addition(a, b); demo.Subtraction(a, b);
Maar met de superclass-referentievariabele (cal in dit geval) kun je de methode multiplication() niet aanroepen, die behoort tot de subclass My_Calculation.
Let op: Een subclass overneemt alle leden (velden, methodes, en geneste klassen) van zijn superclass. Constructors zijn geen leden, dus ze worden niet door subclasses overgeërfd, maar de constructor van de superclass kan worden aangeroepen vanuit de subclass.
Het super-sleutelwoord
Het super-sleutelwoord is vergelijkbaar met het this-sleutelwoord. Hier zijn de scenario's waar super wordt gebruikt:
- Om de leden van de superclass te differentiëren van de leden van de subclass, als ze dezelfde namen hebben.
- Om de constructor van de superclass aan te roepen vanuit de subclass.
Leden differentiëren
Als een klasse de eigenschappen van een andere klasse overneemt, en de leden van de superclass dezelfde namen hebben als die van de subclass, gebruiken we het super-sleutelwoord om deze variabelen te differentiëren:
super.variable super.method();
Voorbeeldcode
In dit programma hebben we twee klassen: Sub_class en Super_class, beide met een methode display() met verschillende implementaties, en een variabele num met verschillende waarden. We roepen de display()-methode van beide klassen aan en printen de waarde van num van beide klassen. Hier zien we het gebruik van super om de leden te differentiëren.
class Super_class {
int num = 20;
// display methode van superclass
public void display() {
System.out.println("Dit is de display methode van superclass");
}
}
public class Sub_class extends Super_class {
int num = 10;
// display methode van sub class
public void display() {
System.out.println("Dit is de display methode van subclass");
}
public void my_method() {
// Instantiëren subclass
Sub_class sub = new Sub_class();
// display() van sub class aanroepen
sub.display();
// display() van superclass aanroepen
super.display();
// waarde van num van subclass printen
System.out.println("waarde van de variabele num in sub class: " + sub.num);
// waarde van num van superclass printen
System.out.println("waarde van de variabele num in super class: " + super.num);
}
public static void main(String args[]) {
Sub_class obj = new Sub_class();
obj.my_method();
}
}
Compileer en voer uit:
javac Sub_class.java java Sub_class
Resultaat:
Dit is de display methode van subclass Dit is de display methode van superclass waarde van de variabele num in sub class: 10 waarde van de variabele num in super class: 20
Superclass Constructor aanroepen
Als een klasse de eigenschappen van een andere klasse overneemt, krijgt de subclass automatisch de default constructor van de superclass. Maar als je een parameterized constructor van de superclass wilt aanroepen, moet je het super-sleutelwoord gebruiken:
super(values);
Voorbeeldcode
class Superclass {
int age;
Superclass(int age) {
this.age = age;
}
public void getAge() {
System.out.println("De waarde van de variabele age in super class is: " + age);
}
}
public class Subclass extends Superclass {
Subclass(int age) {
super(age);
}
public static void main(String args[]) {
Subclass s = new Subclass(24);
s.getAge();
}
}
Resultaat:
De waarde van de variabele age in super class is: 24
IS-A Relatie
IS-A is een manier om te zeggen: Dit object is een type van dat object. Laten we zien hoe het extends-sleutelwoord inheritance bereikt.
public class Animal { }
public class Mammal extends Animal { }
public class Reptile extends Animal { }
public class Dog extends Mammal { }
Op basis van het bovenstaande voorbeeld zijn de volgende stellingen waar in object-georiënteerde termen:
- Animal is de superclass van de Mammal-klasse.
- Animal is de superclass van de Reptile-klasse.
- Mammal en Reptile zijn subclasses van de Animal-klasse.
- Dog is de subclass van zowel Mammal als Animal klassen.
Als we de IS-A relatie overwegen, kunnen we zeggen:
- Mammal IS-A Animal
- Reptile IS-A Animal
- Dog IS-A Mammal
- Dus: Dog IS-A Animal ook
Met het extends-sleutelwoord kunnen subclasses alle eigenschappen van de superclass overerven, behalve de private eigenschappen van de superclass.
We kunnen verzekeren dat Mammal eigenlijk een Animal is met de instanceof-operator.
Voorbeeld
class Animal { }
class Mammal extends Animal { }
class Reptile extends Animal { }
public class Dog extends Mammal {
public static void main(String args[]) {
Animal a = new Animal();
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
Resultaat:
true true true
Nu we een goed begrip hebben van extends, laten we kijken hoe implements wordt gebruikt voor de IS-A relatie.
Over het algemeen wordt implements gebruikt met klassen om de eigenschappen van een interface over te nemen. Interfaces kunnen nooit door een klasse worden uitgebreid (extended).
Voorbeeld
public interface Animal { }
public class Mammal implements Animal { }
public class Dog extends Mammal { }
Het instanceof-sleutelwoord
Laten we de instanceof-operator gebruiken om te controleren of Mammal eigenlijk een Animal is, en Dog eigenlijk een Animal.
Voorbeeld
interface Animal {}
class Mammal implements Animal {}
public class Dog extends Mammal {
public static void main(String args[]) {
Mammal m = new Mammal();
Dog d = new Dog();
System.out.println(m instanceof Animal);
System.out.println(d instanceof Mammal);
System.out.println(d instanceof Animal);
}
}
Resultaat:
true true true
HAS-A Relatie
Deze relaties zijn voornamelijk gebaseerd op gebruik. Dit bepaalt of een bepaalde klasse HAS-A bepaald ding. Deze relatie helpt om duplicatie van code en bugs te verminderen.
Voorbeeld
public class Vehicle {}
public class Speed {}
public class Van extends Vehicle {
private Speed sp;
}
Dit toont dat klasse Van HAS-A Speed. Door een aparte klasse voor Speed te hebben, hoeven we niet de hele code die bij Speed hoort in de Van-klasse te zetten, wat het mogelijk maakt de Speed-klasse in meerdere applicaties te hergebruiken.
In Object-Oriented features hoeven gebruikers zich geen zorgen te maken over welk object het echte werk doet. Om dit te bereiden, verbergt de Van-klasse de implementatiedetails voor de gebruikers van de Van-klasse. Gebruikers vragen de Van-klasse om een actie uit te voeren, en de Van-klasse doet het werk zelf of vraagt een andere klasse om de actie uit te voeren.
Typen Inheritance
Er zijn verschillende typen inheritance, zoals getoond in het diagram.
Belangrijk feit: Java ondersteunt geen multiple inheritance. Dit betekent dat een klasse niet meer dan één klasse kan uitbreiden. Daarom is het volgende illegaal:
public class extends Animal, Mammal {}
Een klasse kan echter een of meer interfaces implementeren, wat Java heeft geholpen de onmogelijkheid van multiple inheritance op te lossen.
Java
- C# Inheritance: Concepten, Types en Praktische Code
- C# Erfelijkheid Beheersen: Herbruikbare, Onderhoudbare Code Bouwen
- Java's final-sleutelwoord begrijpen: variabelen, methoden en klassen
- Java instanceof operator: een uitgebreide gids
- Java geneste static classes begrijpen: gebruik, verschillen en voorbeelden
- Java anonieme inner classes meesteren: definitie, syntax en praktische voorbeelden
- Java Singleton patroon uitgelegd: hoe veilig te implementeren en gebruiken
- Java Reflectie meesteren: klassen, methoden en velden inspecteren tijdens runtime
- Java ObjectOutputStream: Serialisatie, methoden en praktische voorbeelden
- Java Generics: Herbruikbare, type-veilige code bouwen
- Java-bestandsbewerkingen onder de knie krijgen met java.io – Aanmaken, lezen, schrijven en verwijderen