11.6. Structure of Classes and Objects in Java: Inheritance
Inheritance is one of the fundamental concepts of object-oriented programming (OOP), and in Java, it is a crucial part that allows for an efficient and powerful class and object structure. Inheritance allows a class to inherit fields and methods from another class, promoting code reuse and the creation of a hierarchy of related classes.
What is Inheritance?
Inheritance is a mechanism by which a new class, called a subclass, can acquire the properties of an existing class, called a superclass. Inheritance facilitates modularity and code organization, allowing developers to create more specialized classes from more general classes.
How Inheritance Works in Java
In Java, inheritance is performed with the extends
keyword. When a class is derived from another class using extends
, it inherits all public and protected members (fields, methods) of the superclass. Private members of the superclass are not inherited directly, but can be accessed through public or protected methods.
class Animal {
String name;
public void emitSound() {
System.out.println("The animal makes a sound.");
}
}
class Dog extends Animal {
public void emitSound() {
System.out.println("The dog barks: Au Au!");
}
}
In the example above, the Dog
class inherits from the Animal
class. This means that a Dog
object will have access to the name
field and will be able to call the emitSound()
method.
Method Overriding
In inheritance, the subclass has the ability to override the methods of the superclass. This is done to define specific behavior in the subclass. In the previous example, the Sound()
method is overridden in the Dog
class to reflect the specific sound a dog makes.
Using super
The super
keyword is used to directly reference the superclass object. It can be used to call the superclass constructor, as well as to access methods that have been overridden by the subclass.
class Cat extends Animal {
public Gato() {
super.name = "Cat";
}
public void emitSound() {
super.emitSound(); // Call the superclass method
System.out.println("The cat meows: Meow!");
}
}
In the example above, the constructor of the Cat
class assigns a value to the name
field of the Animal
superclass. And the emitarSound()
method first calls the superclass method before adding its own behavior.
Inheritance and Constructors
In Java, constructors are not inherited. However, the subclass can call the superclass's constructors using the super
keyword. This is usually done on the first line of the subclass constructor.
class Bird extends Animal {
public Bird() {
super(); // Call the superclass constructor
// Other initializations
}
}
It is important to note that if the superclass does not have a no-argument constructor (a default constructor), the subclass must explicitly call one of the superclass's available constructors.
Access and Inheritance Modifiers
Access modifiers in Java define how members of a class can be accessed. In inheritance, these modifiers determine what is inherited by the subclass:
- Public: Public members are inherited by the subclass and are accessible from any other class.
- Protected: Protected members are inherited by the subclass and are accessible within the same package or by subclasses in different packages.
- Private: Private members are not inherited by the subclass, but can be accessed indirectly through public or protected methods of the superclass.
Inheritance and Polymorphism
Polymorphism is another key OOP concept that allows objects from different subclasses to be treated as objects of the superclass. This is possible thanks to inheritance and allows the same method to be used in different contexts, depending on the type of object that invokes it.
Animal myAnimal = new Dog();
myAnimal.emitSound(); // Output: The dog barks: Au Au!
In the example above, even if myAnimal
is of type Animal
, the method emitSound()
that is called is that of the class Dog
, thanks to polymorphism.
Final Considerations About Inheritance
Inheritance is a powerful tool, but it must be used with care. The uExcessive inheritance can lead to complex and difficult to maintain class hierarchies. It is important to design systems with inheritance only when it makes sense conceptually, and not just to reuse code. Composition, where one class contains another class, can often be a more flexible alternative to inheritance.
In summary, inheritance in Java allows you to create an efficient structure of classes and objects, promoting code reuse and logical organization. By understanding and correctly applying the concepts of inheritance, method overriding, use of super
, access modifiers, and polymorphism, developers can build robust and scalable systems.