Polymorphism
Polymorphism Interview with follow-up questions
Interview Question Index
- Question 1: What is polymorphism in Java?
- Follow up 1 : Can you provide an example of polymorphism?
- Follow up 2 : What are the types of polymorphism in Java?
- Follow up 3 : How is polymorphism implemented in Java?
- Follow up 4 : What is the advantage of polymorphism?
- Question 2: What is the difference between static and dynamic polymorphism?
- Follow up 1 : Can you provide an example of static and dynamic polymorphism?
- Follow up 2 : When would you use static polymorphism over dynamic and vice versa?
- Follow up 3 : How does Java handle dynamic method dispatch?
- Question 3: What is method overloading and method overriding?
- Follow up 1 : Can you provide an example of method overloading and method overriding?
- Follow up 2 : What are the rules for method overloading and method overriding?
- Follow up 3 : How do method overloading and method overriding support polymorphism?
- Question 4: What is the role of the 'super' keyword in relation to polymorphism?
- Follow up 1 : Can you provide an example where 'super' keyword is used?
- Follow up 2 : What happens if we do not use 'super' keyword?
- Follow up 3 : Can 'super' keyword be used with methods, variables, and constructors?
- Question 5: What is 'upcasting' and 'downcasting' in Java?
- Follow up 1 : Can you provide an example of 'upcasting' and 'downcasting'?
- Follow up 2 : What is the use of 'upcasting' and 'downcasting'?
- Follow up 3 : What happens if downcasting is not done properly?
Question 1: What is polymorphism in Java?
Answer:
Polymorphism in Java is the ability of an object to take on many forms. It allows objects of different classes to be treated as objects of a common superclass. This means that a variable of a superclass type can refer to an object of any subclass of that superclass.
Follow up 1: Can you provide an example of polymorphism?
Answer:
Sure! Here's an example:
class Animal {
public void makeSound() {
System.out.println("Animal is making a sound");
}
}
class Dog extends Animal {
public void makeSound() {
System.out.println("Dog is barking");
}
}
class Cat extends Animal {
public void makeSound() {
System.out.println("Cat is meowing");
}
}
public class Main {
public static void main(String[] args) {
Animal animal1 = new Dog();
Animal animal2 = new Cat();
animal1.makeSound(); // Output: Dog is barking
animal2.makeSound(); // Output: Cat is meowing
}
}
In this example, the Animal
class is the superclass, and the Dog
and Cat
classes are subclasses. The makeSound()
method is overridden in each subclass, allowing the objects to behave differently when the method is called.
Follow up 2: What are the types of polymorphism in Java?
Answer:
There are two types of polymorphism in Java:
Compile-time polymorphism (also known as method overloading): This occurs when there are multiple methods with the same name but different parameters in a class. The appropriate method is chosen at compile-time based on the arguments provided.
Runtime polymorphism (also known as method overriding): This occurs when a subclass provides its own implementation of a method that is already defined in its superclass. The appropriate method is chosen at runtime based on the actual type of the object.
Follow up 3: How is polymorphism implemented in Java?
Answer:
Polymorphism in Java is implemented through method overriding and method overloading.
Method overriding is used to achieve runtime polymorphism. It allows a subclass to provide a different implementation of a method that is already defined in its superclass. To override a method, the subclass must have the same method signature (name and parameters) as the superclass method.
Method overloading is used to achieve compile-time polymorphism. It allows a class to have multiple methods with the same name but different parameters. The appropriate method is chosen at compile-time based on the arguments provided.
Follow up 4: What is the advantage of polymorphism?
Answer:
The advantage of polymorphism in Java is that it allows for code reusability and flexibility. By treating objects of different classes as objects of a common superclass, you can write code that is more generic and can work with a variety of objects. This makes the code easier to maintain and enhances its flexibility, as new subclasses can be added without modifying the existing code.
Question 2: What is the difference between static and dynamic polymorphism?
Answer:
Static polymorphism, also known as compile-time polymorphism, is a mechanism in which the compiler determines which function to call based on the static types of the arguments and the function signature. This is achieved through function overloading and operator overloading.
Dynamic polymorphism, also known as runtime polymorphism, is a mechanism in which the compiler determines which function to call based on the dynamic type of the object at runtime. This is achieved through function overriding and virtual functions.
Follow up 1: Can you provide an example of static and dynamic polymorphism?
Answer:
Sure! Here's an example of static polymorphism:
#include
class Shape {
public:
void draw() {
std::cout << "Drawing a shape" << std::endl;
}
void draw(int x) {
std::cout << "Drawing a shape with size " << x << std::endl;
}
};
int main() {
Shape shape;
shape.draw();
shape.draw(10);
return 0;
}
And here's an example of dynamic polymorphism in C++ using inheritance and virtual functions:
#include
class Shape {
public:
virtual void draw() {
std::cout << "Drawing a shape" << std::endl;
}
};
class Circle : public Shape {
public:
void draw() override {
std::cout << "Drawing a circle" << std::endl;
}
};
int main() {
Shape* shape = new Circle();
shape->draw();
delete shape;
return 0;
}
Follow up 2: When would you use static polymorphism over dynamic and vice versa?
Answer:
Static polymorphism is useful when the behavior of a function can be determined at compile-time based on the static types of the arguments. It can lead to more efficient code execution as the function call is resolved at compile-time.
Dynamic polymorphism is useful when the behavior of a function needs to be determined at runtime based on the dynamic type of the object. It allows for more flexibility and extensibility in the code, as different derived classes can override the base class function to provide their own implementation.
Follow up 3: How does Java handle dynamic method dispatch?
Answer:
In Java, dynamic method dispatch is achieved through the use of virtual functions and method overriding. When a method is declared as virtual
in the base class, it can be overridden by derived classes. The actual method to be called is determined at runtime based on the dynamic type of the object.
Here's an example in Java:
class Shape {
public void draw() {
System.out.println("Drawing a shape");
}
}
class Circle extends Shape {
@Override
public void draw() {
System.out.println("Drawing a circle");
}
}
public class Main {
public static void main(String[] args) {
Shape shape = new Circle();
shape.draw();
}
}
Question 3: What is method overloading and method overriding?
Answer:
Method overloading is a feature in object-oriented programming where multiple methods can have the same name but different parameters. Method overriding is a feature that allows a subclass to provide a specific implementation of a method that is already defined in its superclass.
Follow up 1: Can you provide an example of method overloading and method overriding?
Answer:
Sure! Here's an example of method overloading:
public class Calculator {
public int add(int a, int b) {
return a + b;
}
public double add(double a, double b) {
return a + b;
}
}
In this example, the Calculator
class has two add
methods with the same name but different parameter types. The first add
method takes two integers as parameters and returns an integer, while the second add
method takes two doubles as parameters and returns a double.
And here's an example of method overriding:
public class Animal {
public void makeSound() {
System.out.println("The animal makes a sound.");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
System.out.println("The dog barks.");
}
}
In this example, the Animal
class has a makeSound
method, and the Dog
class overrides this method to provide a specific implementation for dogs.
Follow up 2: What are the rules for method overloading and method overriding?
Answer:
The rules for method overloading are as follows:
- The methods must have the same name.
- The methods must have different parameter types or a different number of parameters.
- The methods may have different return types, but it is not a determining factor for overloading.
The rules for method overriding are as follows:
- The method in the subclass must have the same name, return type, and parameters as the method in the superclass.
- The method in the subclass must be declared with the
@Override
annotation. - The method in the subclass must have the same or a more accessible access modifier than the method in the superclass.
- The method in the subclass must not throw a checked exception that is not declared by the method in the superclass.
Follow up 3: How do method overloading and method overriding support polymorphism?
Answer:
Method overloading and method overriding both support polymorphism, which is the ability of an object to take on many forms. Polymorphism allows objects of different classes to be treated as objects of a common superclass.
Method overloading supports polymorphism by allowing different methods with the same name to be called based on the type and number of arguments passed to them. This allows for more flexibility and convenience when working with objects of different types.
Method overriding supports polymorphism by allowing a subclass to provide a specific implementation of a method that is already defined in its superclass. This allows for specialization and customization of behavior for different types of objects while still maintaining a common interface.
Question 4: What is the role of the 'super' keyword in relation to polymorphism?
Answer:
The 'super' keyword in Java is used to refer to the superclass of a subclass. It is used to access the members (methods and variables) of the superclass from within the subclass. The 'super' keyword is particularly useful in cases where the subclass overrides a method or hides a variable of the superclass, and we want to access the superclass version of the method or variable.
Follow up 1: Can you provide an example where 'super' keyword is used?
Answer:
Sure! Here's an example:
public class Animal {
public void makeSound() {
System.out.println("Animal is making a sound");
}
}
public class Dog extends Animal {
@Override
public void makeSound() {
super.makeSound();
System.out.println("Dog is barking");
}
}
public class Main {
public static void main(String[] args) {
Dog dog = new Dog();
dog.makeSound();
}
}
In this example, the 'super' keyword is used in the makeSound()
method of the Dog
class to call the makeSound()
method of the superclass Animal
. This allows the Dog
class to inherit and extend the behavior of the Animal
class.
Follow up 2: What happens if we do not use 'super' keyword?
Answer:
If we do not use the 'super' keyword, the subclass will override or hide the method or variable of the superclass. This means that when the subclass is used, the overridden or hidden version of the method or variable will be used instead of the superclass version. This can lead to unexpected behavior and can prevent the subclass from accessing or utilizing the functionality provided by the superclass.
Follow up 3: Can 'super' keyword be used with methods, variables, and constructors?
Answer:
Yes, the 'super' keyword can be used with methods, variables, and constructors. When used with methods, it allows the subclass to call and invoke the superclass version of the method. When used with variables, it allows the subclass to access the superclass version of the variable. When used with constructors, it allows the subclass constructor to call and invoke the superclass constructor.
Question 5: What is 'upcasting' and 'downcasting' in Java?
Answer:
'Upcasting' and 'downcasting' are two concepts in Java that are used to convert an object from one type to another.
'Upcasting' is the process of converting an object of a subclass to its superclass type. This is done implicitly and does not require any explicit casting. For example, if we have a class hierarchy where 'Dog' is a subclass of 'Animal', we can upcast a 'Dog' object to an 'Animal' object like this:
Animal animal = new Dog();
Follow up 1: Can you provide an example of 'upcasting' and 'downcasting'?
Answer:
Sure! Here's an example of 'upcasting' and 'downcasting' in Java:
// Upcasting
Animal animal = new Dog();
// Downcasting
Dog dog = (Dog) animal;
Follow up 2: What is the use of 'upcasting' and 'downcasting'?
Answer:
'Upcasting' is useful when we want to treat an object of a subclass as an object of its superclass. This allows us to access only the common methods and fields defined in the superclass, while hiding the specific implementation details of the subclass.
'Downcasting' is useful when we want to access the specific methods and fields of a subclass that are not present in the superclass. It allows us to take advantage of the additional functionality provided by the subclass.
Overall, 'upcasting' and 'downcasting' provide flexibility and polymorphism in Java.
Follow up 3: What happens if downcasting is not done properly?
Answer:
If downcasting is not done properly, it can result in a 'ClassCastException' at runtime. This occurs when we try to cast an object to a subclass type that is not compatible with its actual type.
For example, let's say we have a class hierarchy where 'Cat' is a subclass of 'Animal'. If we try to downcast an 'Animal' object to a 'Cat' object, but the actual object is not an instance of 'Cat', a 'ClassCastException' will be thrown.
To avoid this, it is recommended to use the 'instanceof' operator to check the compatibility of types before performing downcasting.