Java Inheritance
Concept of Inheritance
Inheritance is a cornerstone of Java's object-oriented programming, as it allows the creation of hierarchical class structures.
Inheritance means that a subclass inherits the characteristics and behaviors of a superclass, enabling the subclass object (instance) to have the superclass's fields and methods, or the subclass inherits methods from the superclass, making the subclass exhibit the same behaviors as the superclass.
Inheritance in Real Life:
Rabbits and goats belong to the herbivore category, while lions and leopards belong to the carnivore category.
Herbivores and carnivores both belong to the animal category.
Therefore, inheritance needs to conform to the relationship: is-a, where the superclass is more general and the subclass is more specific.
Although both herbivores and carnivores belong to the animal category, they differ in attributes and behaviors. Thus, the subclass will have the general characteristics of the superclass as well as its own specific characteristics.
Inheritance Format
In Java, the extends
keyword can be used to declare that a class inherits from another class, typically in the following format:
class Superclass {
}
class Subclass extends Superclass {
}
Why Inheritance is Needed
Next, we will illustrate this need through an example.
Develop an animal class, where the animals are penguins and mice, with the following requirements:
- Penguin: Attributes (name, id), Methods (eat, sleep, introduction)
- Mouse: Attributes (name, id), Methods (eat, sleep, introduction)
Penguin Class:
public class Penguin {
private String name;
private int id;
public Penguin(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name + " is eating");
}
public void sleep(){
System.out.println(name + " is sleeping");
}
public void introduction() {
System.out.println("Hello, I am " + id + "号" + name + ".");
}
}
Mouse Class:
public class Mouse {
private String name;
private int id;
public Mouse(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name + " is eating");
}
public void sleep(){
System.out.println(name + " is sleeping");
}
public void introduction() {
System.out.println("Hello, I am " + id + "号" + name + ".");
}
}
From these two code segments, it is evident that there is code duplication, leading to large, bloated code and low maintainability (mainly due to the difficulty of making changes later, which requires modifying a lot of code and is prone to errors). Therefore, to fundamentally solve the problem of these two code segments, inheritance is needed. The common parts of the two code segments can be extracted to form a superclass:
Common Superclass:
public class Animal {
private String name;
private int id;
public Animal(String myName, int myid) {
name = myName;
id = myid;
}
public void eat(){
System.out.println(name + " is eating");
}
public void sleep(){
System.out.println(name + " is sleeping");
}
public void introduction() {
System.out.println("Hello, I am " + id + "号" + name + ".");
}
}
This Animal
class can serve as a superclass. After the penguin class and mouse class inherit from this class, they will have the superclass's attributes and methods, eliminating duplicate code, improving maintainability, and making the code more concise and reusable (reusable mainly because it can be used multiple times without having to write the same code repeatedly).
Penguin Class (After Inheritance):
public class Penguin extends Animal {
public Penguin(String myName, int myid) {
super(myName, myid);
}
}
Mouse Class (After Inheritance):
public class Mouse extends Animal {
public Mouse(String myName, int myid) {
super(myName, myid);
}
}
public class Penguin extends Animal {
public Penguin(String myName, int myid) {
super(myName, myid);
}
}
Mouse Class:
public class Mouse extends Animal {
public Mouse(String myName, int myid) {
super(myName, myid);
}
}
Inheritance Type
It is important to note that Java does not support multiple inheritance, but it does support multilevel inheritance.
Characteristics of Inheritance
-
A subclass inherits non-private properties and methods from its parent class.
-
A subclass can have its own properties and methods, meaning it can extend the parent class.
-
A subclass can implement the methods of the parent class in its own way.
-
Java supports single inheritance, but it also supports multilevel inheritance. Single inheritance means a subclass can only inherit from one parent class. Multilevel inheritance is when, for example, class B inherits from class A, and class C inherits from class B, so B is the parent class of C, and A is the parent class of B. This is a feature that distinguishes Java inheritance from C++ inheritance.
-
Inheritance increases the coupling between classes (a drawback of inheritance, as high coupling means stronger interdependence between code components, leading to poorer code independence).
Inheritance Keywords
Inheritance can be implemented using the extends
and implements
keywords. All classes inherit from java.lang.Object
by default. If a class does not use these keywords, it implicitly inherits from the Object
class (which is in the java.lang
package and does not require import
).
extends Keyword
In Java, class inheritance is single inheritance, meaning a subclass can only have one parent class, so extends
can only inherit from one class.
extends Keyword
public class Animal {
private String name;
private int id;
public Animal(String myName, int myid) {
// Initialize property values
}
public void eat() { // Specific implementation of eating method }
public void sleep() { // Specific implementation of sleeping method }
}
public class Penguin extends Animal{
}
implements Keyword
The implements
keyword allows Java to simulate multiple inheritance by enabling a class to inherit from multiple interfaces (separated by commas).
implements Keyword
public interface A {
public void eat();
public void sleep();
}
public interface B {
public void show();
}
public class C implements A,B {
}
super and this Keywords
The super
keyword is used to access members of the parent class, referring to the parent of the current object.
The this
keyword refers to the current object.
Example
class Animal {
void eat() {
System.out.println("animal : eat");
}
}
class Dog extends Animal {
void eat() {
System.out.println("dog : eat");
}
void eatTest() {
this.eat(); // this calls its own method
super.eat(); // super calls the parent class method
}
}
public class Test {
public static void main(String[] args) {
Animal a = new Animal();
a.eat();
Dog d = new Dog();
d.eatTest();
}
}
Output:
animal : eat
dog : eat
animal : eat
final Keyword
The final
keyword can be used to modify variables (including class attributes, object attributes, local variables, and parameters), methods (both class methods and object methods), and classes.
The meaning of final
is "final," or "unchangeable."
Using the final
keyword to declare a class means the class is defined as the final class and cannot be inherited, or it can be used to modify a method, making it impossible for subclasses to override it:
-
Declaring a class:
final class ClassName {// class body}
- Declaration Method:
modifier(public/private/default/protected) final returnType methodName(){//method body}
Note: A class defined with final
does not have its properties and methods as final
.
Constructors
Subclasses do not inherit the constructor of their parent class; they merely invoke it (implicitly or explicitly). If the parent class constructor has parameters, the subclass constructor must explicitly call the parent class constructor using the super
keyword with the appropriate parameter list.
If the parent class constructor has no parameters, the subclass constructor does not need to use the super
keyword to call the parent class constructor; the system will automatically call the parent class's no-argument constructor.
Example
class SuperClass {
private int n;
SuperClass(){
System.out.println("SuperClass()");
}
SuperClass(int n) {
System.out.println("SuperClass(int n)");
this.n = n;
}
}
// SubClass inherits from SuperClass
class SubClass extends SuperClass{
private int n;
SubClass(){ // Automatically calls the no-argument constructor of the parent class
System.out.println("SubClass");
}
public SubClass(int n){
super(300); // Calls the parameterized constructor of the parent class
System.out.println("SubClass(int n):"+n);
this.n = n;
}
}
// SubClass2 inherits from SuperClass
class SubClass2 extends SuperClass{
private int n;
SubClass2(){
super(300); // Calls the parameterized constructor of the parent class
System.out.println("SubClass2");
}
public SubClass2(int n){ // Automatically calls the no-argument constructor of the parent class
System.out.println("SubClass2(int n):"+n);
this.n = n;
}
}
public class TestSuperSub{
public static void main (String args[]){
System.out.println("------SubClass Inheritance------");
SubClass sc1 = new SubClass();
SubClass sc2 = new SubClass(100);
System.out.println("------SubClass2 Inheritance------");
SubClass2 sc3 = new SubClass2();
SubClass2 sc4 = new SubClass2(200);
}
}
Output:
------SubClass Inheritance------
SuperClass()
SubClass
SuperClass(int n)
SubClass(int n):100
------SubClass2 Inheritance------
SuperClass(int n)
SubClass2
SuperClass()
SubClass2(int n):200