How is super()
Called? Implicitly vs. Explicitly
The super()
keyword is used to call the parent class constructor from a subclass. It can be used in two ways:
1. Explicitly
- You can call the parent class constructor explicitly using
super()
within the subclass constructor:
class A {
A(int x) {
System.out.println("Parent Constructor with value: " + x);
}
}
class B extends A {
B() {
super(10); // Explicit call to parent constructor
System.out.println("Child Constructor");
}
}
public class Test {
public static void main(String[] args) {
B obj = new B();
}
}
- Output:
Parent Constructor with value: 10
Child Constructor
2. Implicitly
- If you do not call
super()
explicitly, Java automatically inserts a no-argumentsuper()
call to invoke the parent class’s default constructor if it exists.
class A {
A() {
System.out.println("Parent Constructor");
}
}
class B extends A {
B() {
// Implicit call to super() (Java inserts it)
System.out.println("Child Constructor");
}
}
public class Test {
public static void main(String[] args) {
B obj = new B();
}
}
- Output:
Parent Constructor
Child Constructor
Important Note:
- If the parent class doesn’t have a default constructor, then the subclass must call the parameterized constructor using
super(...)
.
Polymorphism in Java
Polymorphism is the ability of an object to take on many forms. It allows a single action to behave differently based on the context, typically via method overriding and method overloading.
Why is It Called Polymorphism?
The term comes from Greek, where poly means "many" and morph means "form". In Java, polymorphism allows methods to have multiple forms.
Types of Polymorphism
- Compile-time Polymorphism (Static Polymorphism): Achieved through method overloading.
- Runtime Polymorphism (Dynamic Polymorphism): Achieved through method overriding.
Why We Use Polymorphism
- Reusability: We can use a single method for multiple purposes.
- Flexibility: Objects can be treated as their parent type, allowing for more flexible code.
How to Use Polymorphism?
- Method Overloading (Compile-time)
- Method Overriding (Runtime)
Method Overloading and Overriding
Method Overloading
Method overloading occurs when you have multiple methods with the same name but with different parameter types or number of parameters.
- Example:
class Calculator {
int add(int a, int b) {
return a + b;
}
double add(double a, double b) {
return a + b;
}
}
public class Test {
public static void main(String[] args) {
Calculator calc = new Calculator();
System.out.println(calc.add(10, 20)); // int version
System.out.println(calc.add(10.5, 20.5)); // double version
}
}
- Why It’s Called Overloading: The method name remains the same, but the parameters change, so it's called "overloading."
Method Overriding
Method overriding occurs when a subclass provides its own implementation of a method that is already defined in the superclass.
- Example:
class Animal {
void sound() {
System.out.println("Animal makes a sound");
}
}
class Dog extends Animal {
@Override
void sound() {
System.out.println("Dog barks");
}
}
public class Test {
public static void main(String[] args) {
Animal animal = new Dog();
animal.sound(); // Calls Dog's sound method
}
}
- Why It’s Called Overriding: The subclass overrides the method to provide a specific behavior.
Rules for Overloading and Overriding:
-
Overloading:
- Must be done in the same class.
- Must differ in the number or type of parameters.
- Can change the return type, but not mandatory.
-
Overriding:
- Must have the same method signature (same name, same parameters).
- Can’t change the return type (must be covariant).
- The access modifier can be broader but not more restrictive (e.g.,
public
can overrideprotected
but not vice versa).
What is Late Binding and Binding?
Binding:
Binding refers to the process of associating a method call to the method definition (implementation) at runtime or compile-time.
Late Binding (Dynamic Binding):
- Occurs at runtime when the method to be invoked is determined dynamically.
- It’s a feature of runtime polymorphism (method overriding).
Example: In the previous method overriding example, the method called (sound()
) depends on the object type at runtime, not the reference type. This is late binding.
Early Binding (Static Binding):
- Occurs at compile-time when the method to be invoked is determined statically.
- It’s a feature of method overloading.
Types of Inheritance
Inheritance in Java can be categorized into different types:
-
Single Inheritance:
- One class inherits from another.
- Example:
class A extends B
-
Multilevel Inheritance:
- A class inherits from a class that is already a subclass.
- Example:
class A extends B
andclass B extends C
-
Hierarchical Inheritance:
- Multiple classes inherit from a single parent class.
- Example:
class A extends B
,class C extends B
-
Multiple Inheritance (Not Supported in Java):
- A class inherits from more than one class. Java doesn’t support multiple inheritance directly to avoid ambiguity.
Can’t do: class A extends B, C
is not valid in Java.
-
Hybrid Inheritance (Combination of Multiple Inheritance Types):
- A combination of more than one type of inheritance (single, multilevel, or hierarchical).
- Example: A class inherits from a class, which itself is derived from another.
One Class Can Contain One extends
Keyword
- Why?: A class can only inherit from one superclass because Java does not support multiple inheritance. This helps avoid complexity and ambiguity.
Can We Change the Return Type or Access Modifier While Overriding?
- Return Type: In method overriding, the return type can change but must be covariant (i.e., the return type in the subclass must be the same or a subclass of the return type in the superclass).
class A {
Number getNumber() { return 10; }
}
class B extends A {
Integer getNumber() { return 20; } // Valid: Integer is subclass of Number
}
-
Access Modifier: The access modifier can be broader (e.g.,
protected
topublic
), but it can’t be more restrictive (e.g.,protected
toprivate
).
Day 16 Key Takeaways:
-
super()
is used to invoke a parent constructor, either explicitly or implicitly. - Polymorphism allows methods to take many forms, achieved via method overloading (compile-time) and overriding (runtime).
- Method overloading requires the same method name but different parameters, while method overriding allows subclasses to provide specific implementations of inherited methods.
- Late Binding occurs at runtime (method overriding), while early binding happens at compile-time (method overloading).
- Java supports types of inheritance like single, multilevel, and hierarchical, but multiple inheritance is not allowed.