What is the benefit of Dynamic Polymorphism in Java? - java

I am studying up on my Java Programming and Object Oriented Programming. I keep getting hung up on what the benefit of Dynamic Polymorphism is?
Take a look at my sample program below.
Why would I use example 1 over example 2?
class SuperHero {
private String power = ("Generic Power");
public void useSuperPower() {
System.out.println(power);
}
}
class Spiderman extends SuperHero {
private String power = ("Web sling!");
public void useSuperPower() {
System.out.println(power);
}
}
class Wolverine extends SuperHero {
private String power = ("Hack and Slash!");
public void useSuperPower() {
System.out.println(power);
}
}
class main {
public static void main (String args[]) {
//example 1
SuperHero hero = new SuperHero();
SuperHero hero1 = new Spiderman();
SuperHero hero2 = new Wolverine();
hero.useSuperPower();
hero1.useSuperPower();
hero2.useSuperPower();
//example 2
Spiderman test = new Spiderman();
Wolverine test2 = new Wolverine();
test.useSuperPower();
test2.useSuperPower();
}
}

The easiest example of when dynamic polymorphism is powerful is in collections. We can collect objects of different classes together, and use them all the same, so long as they all share a single parent interface. For instance:
List<SuperHero> avengers = new ArrayList<>();
avengers.add(new Spiderman());
avengers.add(new Wolverine());
System.out.println("Avengers Assemble!");
for(SuperHero hero : avengers){
hero.useSuperPower();
}
It also allows for APIs to be very flexible. We can create methods which expect one interface, but later on pass them an object of a child type, without having to recreate that method. For instance:
public void usePower(SuperHero hero){
hero.useSuperPower();
}
Here, we can call this method with object which extends SuperHero. (That example is a bit lame, since we could just call the useSuperPower() method directly, but hopefully you get the point.)
Basically, polymorphism allows us to create classes which all do the same thing, but do it differently, and then use them (almost) interchangeably.

You'll probably never use example 1 directly. HOWEVER, you may end up in example 1 anyways (and hence Dynamic Polymorphism has value).
Let's say the two of us are coding a game together, and you've written the superhero hirearchy as you have in the question. Over on my side, I've written a class called JusticeLeagueScheduler with the method:
public JusticeLeagueScheduler {
public static Superhero getAvaiableHero() {
// ...
}
}
Which allows you to get access to a superhero who can help save the day. Furthermore, suppose that the method getAvailableHero() is absurdly long, as it needs to take into account how often each superhero has been used, Logan's current BAC, Peter Parker's school schedule, etc etc etc.
When you call that method, you'll do so like this:
SuperHero superhero = JusticeLeagueScheduler.getAvailableHero();
At this point, you have no idea which hero you have, only that it is an instance or subclass of class SuperHero. Thus, you are in the situation in example 1. You can't call Wolverine methods on superhero, because it might be Wolverine, but it also might not be. You can call only methods defined by class SuperHero (or its parent type Object) on superhero.
However, it will still be the instance it is. If my method returns a Wolverine instance to you, and you call userSuperPower(), you will get "Hack and Slash", even though you couldn't have predicted that beforehand.

In example 1, hero, hero1 and hero2 are all of type SuperHero. When you use the same method on different SuperHero objects, they behave in different manner. That is polymorphism.
However, in example 2, hero, hero1 and hero2 are all of different types. So, the example doesn't demonstrate polymorphism.

Yes, you are saving yourself time and saving yourself code.
Polymorphism in Java
Polymorphism in java is a concept by which we can perform a single
action by different ways. Polymorphism is derived from 2 greek words:
poly and morphs. The word "poly" means many and "morphs" means forms.
So polymorphism means many forms.
There are two types of polymorphism in java: compile time polymorphism
and runtime polymorphism. We can perform polymorphism in java by
method overloading and method overriding.
If you overload static method in java, it is the example of compile
time polymorphism. Here, we will focus on runtime polymorphism in
java.
Runtime Polymorphism in Java
Runtime polymorphism or Dynamic Method Dispatch is a process in which
a call to an overridden method is resolved at runtime rather than
compile-time.
In this process, an overridden method is called through the reference
variable of a superclass. The determination of the method to be called
is based on the object being referred to by the reference variable.
Let's first understand the upcasting before Runtime Polymorphism.
Now let's take an example where you will need to convert one Spiderman object to SuperHero class, would you be able to do so if you instantiate without dynamic polymorphism. Answer is no.
Read more about Collection API and you will know why we need Dynamic Polymorphism.
Read this answer to understand the concept.
So, if you do the following:
SuperHero hero1 = new Spiderman();
SuperHero hero2 = new Wolverine();
You can also do:
SuperHero hero3 = new Spiderman();
hero3 =(Superhero) hero2;
Which you won't be able to do if you don't apply polymorphism.

Related

How do methods from a class are shared between objects?

Reading "Thinking in Java" by Bruce Eckel at the moment. Reached "this" keyword point. It's not clear for me how really objects and "this" work. Bruce Eckel in his book says:
If you have two objects of the same type called a and b, you might wonder how it is that you can call a method peel( ) for both those objects:
//: initialization/BananaPeel.java
class Banana { void peel(int i) { /* ... */ } }
public class BananaPeel {
public static void main(String[] args) {
Banana a = new Banana(),
b = new Banana();
a.peel(1);
b.peel(2);
}
} ///:~
If there’s only one method called peel( ), how can that method know whether it’s being called for the object a or b?
To allow you to write the code in a convenient object-oriented syntax in which you “send a message to an object,” the compiler does some undercover work for you. There’s a secret first argument passed to the method peel( ), and that argument is the reference to the object that’s being manipulated. So the two method calls become something like:
Banana.peel(a, 1);
Banana.peel(b, 2);
So, when we create an object it has it own methods copied from the class.
A obj = new A();
obj.callMethod(); //<-- object uses it's own method, not the class, right?
And according to the book the methods of a class are shared somehow between all
the objects created from this class.
How does this mechanism work in the result?
I don’t get this part:
If you have two objects of the same type called a and b, you might wonder how it is that you can call a method peel( ) for both those objects.
If there’s only one method called peel( ), how can that method know whether it’s being called for the object a or b?
What does it mean “only one method called peel()”
We have all the methods from the class created for each object. So we just call the method from the object.
What did Bruce Eckel mean?
If you and I both laugh when something is funny, you may say that we share the ability to laugh.
I am thinking of sharing methods between instances of a class in much the same way. Bananas share the property that they can be peeled. The Banana class specifies what Banana objects are and what they can do. Some have described the class as a template for creating objects or a rubber stamp for stamping them. All bananas can be peeled, but the programmer still decides which ones s/he actually peels, and when. In programming terms: The Banana class specifies that every banana has a peel method, and what that method is.
When Eckel does a.peel(1); he’s specifying that he is peeling banana a (and not banana b just yet). As far as I am concerned, this all you as an object-oriented programmer need to know to use bananas and their methods.
Classes, objects and instance methods are described in many ways in many places. You may see if it helps you to search for other descriptions to supplement the one by Eckel.

InputStream and OutputStream in java/Android [duplicate]

I am learning java concepts.
I got a doubt in java inheritance concept.
In inheritance we can assign subclass instance to a base class reference
and with that we can access only base class function.
and we can assign any subclass instance in the hierarchy of inheritance to base class reference.For an type of instance assigning to a particular base class reference we can access only base class functions and i didn't find any difference.
Can any one give me actual concept
why we have to assign subclass instances to base class references?
what is the need to do that?
Instead we can access those base class functions from subclass reference only know.
Explain by considering a particular base class and many subclasses in the hierarchy.
The reason why you may want to do this is to create more robust designs. Take for example the Collections Framework in Java. You have a List interface and then you have two implementations, ArrayList and LinkedList.
You can write your program to use a LinkedList specifically or an ArrayList specifically. However, your program then depends on those specific implementations.
If you write your program to depend on the super type, List, instead then your program can work for either of the List implementations. Lets say you want to write a method that does something to a List and you wrote this:
public void doSomething(ArrayList a){}
This method can only be called with an ArrayList, not a LinkedList. Suppose that you wanted to do the same thing with a LinkedList? Do you then duplicate your code? No.
public void doSomething(List l){}
Will be able to accept either type of List.
The principle behind this is program to an interface not an implementation. That is, List defines the functions of ALL lists.
There are many many examples of this usage.
Inheritance and Polymorphism are cornerstones of object-oriented programming and serve a few different purposes, in short:
Code reuse by extending a base class with specific functionality,
Interface design by providing an abstract set of functionality, which where different implementations are tailored to different requirements and
Encapsulation by hiding specific functionality, which isn't needed in certain contexts
among others.
The last point also highlights, why one might use a restricted set of functionality, even in a case the actual implementation provides more than that. Take for example the Collection interface. By using this interface, we focus on methods like isEmpty, contains or size but not the actual implementation.
What you've described is the essence of polymorphism. It's a word from the Greek that means "many forms".
If I gave you a simple hierarchy like this, you can see how the test code can get different calculation implementations out of each object without concerning itself about what kind of Shape it was dealing with:
public interface Shape
{
double calculateArea();
}
class Circle implements Shape
{
private double radius;
Circle(double r) { this.radius = r; }
public double calculateArea() { return Math.PI*radius*radius; }
}
class Square implements Shape
{
private double side;
Square(double s) { this.side = s; }
public double calculateArea() { return side*side; }
}
// This would be a separate JUnit or TestNG annotated test.
public class ShapeTest
{
#Test
public void testCalculateArea()
{
Map<Shape, Double> expected = new HashMap<Shape, Double>()
{{
put(new Circle(1.0), Math.PI);
put(new Square(1.0), 1.0);
}};
for (Shape shape : expected.keySet())
{
Assert.assertEquals(expected.get(shape), shape.calculateArea());
}
}
}
Polymorphism.
I am a method that gives you a List<String>. All you need to know about the thing I've actually given you is that it's a list and has the behaviour and semantics of a list, i.e. you can put things in it, it'll maintain their ordering, and you can iterate over it.
What you don't need to know is how I'm storing things, how I'm making them accessible, etc. That's not important. For all you care, it could be a LinkedList<String>, an ArrayList<String> or something entirely new. Suffice it to say, I've picked something, and you can happily use it.
You're absolutely right that when you're using inheritance to extend classes and add new behaviour, then you need to reference the subclass to be able to access it. The two approaches are somewhat complimentary, but different, use cases.
Let us say Vehicle is the base class and Car and Plane are subclasses. Let us say Vehicle has has a method move().
Car overrides this by going on road. Plane overrides this by flying.
Why move() should be part of Vehicle base class?
Because any Vehicle can move(). But we can't implement move() in Vehicle because all vehicles doesn't move the same way i.e. there is no common behavior. We still want this in the base class so that we can have polymorphic behavior i.e. we can write code like below. As you can see there is only one method called runVehicle(...) that can work on any Vehicle class.
void runVehicle(Vehicle v)
{
v.move();
}
Car c=new Car();
runVehicle(c);
Plane p=new Plane();
runPlane(p);
There is no real need to do that, except when the API demands it. For example, if in a particular API or code library there is a
void ReallyUsefulFunction(BaseClass instance)
that you would like to use, you can derive a class fom BaseClass and implement its methods in the SubClass. Then you can now pass the subclass to the function.
Still, technically, you could implement your own
void MyReallyUsefulFunction(MyClass instance)
which imitates the same functionality. But like what MYYM had explained, the benefits of code reuse etc. can be huge, and that is when you will want to take advantage of polymorphism.

When to use abstract class as type

So while trying to understand abstract classes, there is still one thing I am confused on. When do you ever want to declare an object type of its abstract class. For example
public abstract class GameObject
{
public abstract void draw();
public static void main(String[] args)
{
GameObject player = new Player();
Menu menu = new Menu();
}
}
public class Player extends GameObject
{
override
public void draw()
{
// Something
}
}
public class Menu extends GameObject
{
override
public void draw()
{
// Something
}
}
Normally, I would just instaniate a player object of player type. However, I have seen abstract classes used as the variable type of the new object. When would you ever choose to do this? Thanks!
You would do that every time you need the variable to be an instance of the abstract class, but don't really care about what the concrete type is (and don't want the rest of the code to assume a specific subclass is used). For example:
GameObject[] gameObjects = new GameObject[] {new Menu(), new Player()};
drawAll(gameObjects);
...
private void drawAll(GameObject[] gameObjects) {
for (GameObject gameObject : gameObjects) {
gameObject.draw();
}
}
The abstract type is often used as a return type (because you don't want the caller to know what concrete type is returned: it could change later, or could vary based on the arguments of the configuration).
It's also often used as method parameter type, so that the method can accept an argument of any subclass of the abstract type and use it polymorphically.
And of course, as an array/collection type, to be able to store instances of multiple subclasses in a unique collection.
Say you want to add functionality to make a particular GameObject invisible. A raw implementation would look like:
void makeInvisible(GameObject object) { ... }
This method is supposed to work with any kind of GameObject (and is able to make them all invisible -- or it can throw an IllegalArgumentException if the "wrong" kind of object is passed).
Your question however seems to be particularly concerned with this kind of declaration:
GameObject gameObject = new Player(); // why on earth would you do this -- you wonder
First think of how often you've seen the following:
List<String> stringList = new ArrayList<>();
And yet, this is recommended as best practice because the rest of the code should not be aware of the particular List implementation chosen. You can change that to a LinkedList later on without changing anything but that line above.
If you can find no reasonable scenario where such a declaration would make sense for your abstraction, it is probably a symptom for one of the following:
You're not willing to make use of polymorphism: that is, you want to define the specific logic for each subtype and never deal with them "generically" -- like in the makeInvisible example above
Your abstraction isn't buying you much; in other words, it is not usable as such and you should probably re-consider your design.
In your particular case, that abstract class is not particularly well-designed.
First of all, it makes the main() method visible to all its subclasses and there's no reason why you would want to have main in scope for Player or Menu.
Secondly, it would suit better as an interface (Drawable, maybe), since all it does is define the signature for the draw method. This change would make its polymorphic capabilities more obvious, as you should be able to spot where you need to treat objects as mere Drawables and this should answer your question.
Let's say you have an abstract Animal class, with methods such as eat(), sound(), etc.
You can create classes that extend this Animal class, let's say Dog and Cat.
If there are abstract methods in the abstract class (which isn't mandatory), you'll need to implement that method in each type that extends Animal.
If the method is not abstract, you can still override it if you want it to do something different from the main class.
If you still don't fully understand try this video https://www.youtube.com/watch?v=TyPNvt6Zg8c.

Why should I reference the base class when I can access all the methods just as well by referencing the subclass?

I am learning java concepts.
I got a doubt in java inheritance concept.
In inheritance we can assign subclass instance to a base class reference
and with that we can access only base class function.
and we can assign any subclass instance in the hierarchy of inheritance to base class reference.For an type of instance assigning to a particular base class reference we can access only base class functions and i didn't find any difference.
Can any one give me actual concept
why we have to assign subclass instances to base class references?
what is the need to do that?
Instead we can access those base class functions from subclass reference only know.
Explain by considering a particular base class and many subclasses in the hierarchy.
The reason why you may want to do this is to create more robust designs. Take for example the Collections Framework in Java. You have a List interface and then you have two implementations, ArrayList and LinkedList.
You can write your program to use a LinkedList specifically or an ArrayList specifically. However, your program then depends on those specific implementations.
If you write your program to depend on the super type, List, instead then your program can work for either of the List implementations. Lets say you want to write a method that does something to a List and you wrote this:
public void doSomething(ArrayList a){}
This method can only be called with an ArrayList, not a LinkedList. Suppose that you wanted to do the same thing with a LinkedList? Do you then duplicate your code? No.
public void doSomething(List l){}
Will be able to accept either type of List.
The principle behind this is program to an interface not an implementation. That is, List defines the functions of ALL lists.
There are many many examples of this usage.
Inheritance and Polymorphism are cornerstones of object-oriented programming and serve a few different purposes, in short:
Code reuse by extending a base class with specific functionality,
Interface design by providing an abstract set of functionality, which where different implementations are tailored to different requirements and
Encapsulation by hiding specific functionality, which isn't needed in certain contexts
among others.
The last point also highlights, why one might use a restricted set of functionality, even in a case the actual implementation provides more than that. Take for example the Collection interface. By using this interface, we focus on methods like isEmpty, contains or size but not the actual implementation.
What you've described is the essence of polymorphism. It's a word from the Greek that means "many forms".
If I gave you a simple hierarchy like this, you can see how the test code can get different calculation implementations out of each object without concerning itself about what kind of Shape it was dealing with:
public interface Shape
{
double calculateArea();
}
class Circle implements Shape
{
private double radius;
Circle(double r) { this.radius = r; }
public double calculateArea() { return Math.PI*radius*radius; }
}
class Square implements Shape
{
private double side;
Square(double s) { this.side = s; }
public double calculateArea() { return side*side; }
}
// This would be a separate JUnit or TestNG annotated test.
public class ShapeTest
{
#Test
public void testCalculateArea()
{
Map<Shape, Double> expected = new HashMap<Shape, Double>()
{{
put(new Circle(1.0), Math.PI);
put(new Square(1.0), 1.0);
}};
for (Shape shape : expected.keySet())
{
Assert.assertEquals(expected.get(shape), shape.calculateArea());
}
}
}
Polymorphism.
I am a method that gives you a List<String>. All you need to know about the thing I've actually given you is that it's a list and has the behaviour and semantics of a list, i.e. you can put things in it, it'll maintain their ordering, and you can iterate over it.
What you don't need to know is how I'm storing things, how I'm making them accessible, etc. That's not important. For all you care, it could be a LinkedList<String>, an ArrayList<String> or something entirely new. Suffice it to say, I've picked something, and you can happily use it.
You're absolutely right that when you're using inheritance to extend classes and add new behaviour, then you need to reference the subclass to be able to access it. The two approaches are somewhat complimentary, but different, use cases.
Let us say Vehicle is the base class and Car and Plane are subclasses. Let us say Vehicle has has a method move().
Car overrides this by going on road. Plane overrides this by flying.
Why move() should be part of Vehicle base class?
Because any Vehicle can move(). But we can't implement move() in Vehicle because all vehicles doesn't move the same way i.e. there is no common behavior. We still want this in the base class so that we can have polymorphic behavior i.e. we can write code like below. As you can see there is only one method called runVehicle(...) that can work on any Vehicle class.
void runVehicle(Vehicle v)
{
v.move();
}
Car c=new Car();
runVehicle(c);
Plane p=new Plane();
runPlane(p);
There is no real need to do that, except when the API demands it. For example, if in a particular API or code library there is a
void ReallyUsefulFunction(BaseClass instance)
that you would like to use, you can derive a class fom BaseClass and implement its methods in the SubClass. Then you can now pass the subclass to the function.
Still, technically, you could implement your own
void MyReallyUsefulFunction(MyClass instance)
which imitates the same functionality. But like what MYYM had explained, the benefits of code reuse etc. can be huge, and that is when you will want to take advantage of polymorphism.

how to know which constructor was used in creating an object?

Consider
Class A has two constructors new A(int), new A(int, String)
also
it has a method show()
Then given a statement like,
A a1= new A(4);
A a2= new A(3, "foo");
and later in code (or in some methods where these object were passed)
a1.show();
a2.show();
new A(3).show();
and
new A(2,"bar").show();
If I wanted to differentiate between these show methods based on the objects (a1 and a2) as well as based on class instance expression (calling show directly on constructors) and did not know which constructor was used (especially for the objects a1 and a2) how do I find that out--say reflectively?
The only way to do this would be to have each constructor set a different variable to indicate that it was used.
But I agree with Tom; this sounds like a bad idea. It shouldn't matter how you created an object (because a constructor may not even have been used at all, say, in serialisation), it should only matter that all it's properties (public or not) are set appropriately, to reflect the state it needs to be in.
Maybe A should be two different classes (each with a different constructor); or two different subclasses of a common base class: in that way, each class could have it's own distinct implementation of the show method.
Alternatively, have a data member inside A (perhaps a boolean, or the string) whose value is set differently by each constructor.
If two classes have different sets of behavior then they are two distinct classes. A single class should not behave differently based on how it was constructed.
Agree that you're better off using two separate classes, in which case you could use polymorphism (example in C#),
public class Base
{
public BaseClass()
public virtual void Show
{
// show stuff
}
}
public class A : Base
{
public A(int i)
public override void Show()
{
// show A stuff
}
}
public class B : Base
{
public B(int i, String s)
public override void Show()
{
// show B stuff
}
}
Then call the classes
Base a1= new A(4);
Base a2= new B(3, "foo");
and it should be easy to differentiate between these show methods based on the a1 and a2 objects.
It is not possible to determine by reflection which constructor was used to instantiate an object. Why not simply set an instance variable to a different value in each constructor to track which one was called?
So all four ways of calling show should perform a difference action?
Why and what is the difference between each of the actions?
Without knowing more we can only make wild guesses. It does sound like a job for two or maybe even four classes (plus an base class/interface) and a factory to create them.
If the question is purely theoretical - No, you can not tell at run time the difference between:
A a = new A();
a.show();
and
new A().show();
The only way to do so would be to exam the source¹, so you would have to include the source and compile with full source numbers included. The parse the source code to work out how it was called.

Categories

Resources