Understand Upcasting and other key concepts in Object-Oriented Programming such as inheritance, polymorphism, abstraction, and method overriding in Java with practical examples.
Upcasting means converting a subclass object into a superclass reference. It is done automatically and allows access only to the superclass methods and variables.
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
void sound() {
System.out.println("Dog barks");
}
}
public class TestUpcasting {
public static void main(String[] args) {
Animal a = new Dog(); // Upcasting
a.sound(); // Output: Dog barks
}
}
In the above code, the reference variable of parent class (Animal) refers to the object of child class (Dog), which shows polymorphism in action.
1. Increases flexibility and reusability of code.
2. Enables runtime polymorphism.
3. Makes code more generic and easier to maintain.
Downcasting converts a superclass reference back to subclass reference. It requires explicit casting and should be done carefully to avoid runtime exceptions.
Animal a = new Dog(); // Upcasting
Dog d = (Dog) a; // Downcasting
d.sound();
Downcasting lets us access subclass-specific methods, but always ensure type safety using the instanceof keyword.
Encapsulation: Binding data and methods together.
Inheritance: Acquiring properties from parent class.
Polymorphism: Performing the same action in multiple forms.
Abstraction: Hiding implementation details and showing only essential features.
Method Overriding: Redefining parent class methods inside a child class.
abstract class Shape {
abstract void draw();
}
class Circle extends Shape {
void draw() {
System.out.println("Drawing Circle");
}
}
class Square extends Shape {
void draw() {
System.out.println("Drawing Square");
}
}
public class TestShapes {
public static void main(String[] args) {
Shape s1 = new Circle(); // Upcasting
Shape s2 = new Square();
s1.draw();
s2.draw();
}
}
This example demonstrates abstraction, inheritance, polymorphism, and upcasting all working together to achieve object-oriented design.
1. Always ensure type compatibility before downcasting.
2. Use instanceof to prevent runtime errors.
3. Maintain a clear and consistent class hierarchy.
4. Use upcasting for flexibility and runtime polymorphism.