Is this still polymorphism? - java

While coding, I got an interesting doubt about polymorphism and I couldn't understand a solution for this.
public class Animal {
public void getLegs() {
SOP("4 legs");
}
}
public class Kangaroo extends Animal {
public void getLegs() {
SOP("2 legs");
}
public static void main(String[] args) {
Animal a = new Kangaroo(); // without changing this how can I get Animal getLegs
SOP(a.getLegs()); // Important Line
}
}
Now If I want to call the getLegs method of Animal, how do I? Is it possible? Is it still polymorphism?

Yes, it is the most basic form of demonstrating polymorphisim.
Basically you are dealing with an Animal named a. When you call a.getLegs() your code doesn't bind to the implementation of getLegs() in Animal, rather it binds to the lowest sub-class implementation, getLegs() in Kangraoo().
If the Animal has an implementation, it is said to be hidden by the subclass implementation. If Animal has no implementation, then it is not possible to construct stand-alone classes of Animal as they lack implementations for all of the required methods, and under such a circumstance, Animal is said to be an abstract class (one that cannot be constructed directly, but only can be constructed by it's sub classes).

If you really want to call your method for Animal, and you can employ a static method, you can use hiding instead of overriding.
It works as follows: for static methods only, the called method is the one related to the declared type, not the object instance. In other words, it follows the class because the method is a class method, not an instance method.
An example, adapted from this page:
public class Animal {
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
public void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
public class Kangaroo extends Animal {
public static void testClassMethod() {
System.out.println("The class method" + " in Kangaroo.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Kangaroo.");
}
public static void main(String[] args) {
Kangaroo myRoo = new Kangaroo();
Animal myAnimal = myRoo;
myRoo.testInstanceMethod();
myAnimal.testInstanceMethod();
Kangaroo.testClassMethod();
Animal.testClassMethod();
}
}
The result will be (pay attention to the 3rd and 4th lines, as opposed to the 1st and 2nd):
The instance method in Kangaroo.
The instance method in Kangaroo.
The class method in Kangaroo.
The class method in Animal.

In Java it's not possible to access Animal's implementation. It will always return Kangaroo's version.
(Note in C# it is possible by tagging the overriding method with "new", but it's a fairly specialised use case).
Accessing what appears to be an Animal but getting the behaviour specified by Kangaroo is exactly what polymorphism is - the ability for a child object to be substituted wherever its parent is expected.
In general you wouldn't want to have the calling code know about the inheritance hierarchy because this would tightly couple your code together. If you genuinely need to access Animal's implementation of this method it suggests your design is probably wrong.

The spirit of Polymorphism is to execute different code decided at runtime. To make it more clear, I'll modify your code a bit.
public class Animal {
public void getLegs(){
SOP('4 legs');
}
}
public class Kangaroo extends Animal{
public void getLegs(){
SOP('2 legs');
}
public static void main(String[] args){
Animal a = new Kangaroo(); //without changing this how can I get Animal getLegs
Kangaroo kng= new Kangaroo ();
Animal an = new Animal();
SOP(a.getLegs()); // Kangaroo's version is called
SOP(kng.getLegs()); //Again, Kangaroo's version is called
SOP(an.getLegs()); //Animal version is called
}
}
and Yes, as all say you can't call Animal from your line Animal a = new Kangaroo();..as none will want to do it. Rather he will directly write. Animal a = new Animal();..
So finally it is the object not referance which decides which method will be called

Now If I want to call the getLegs method of Animal, how do I? Is it possible?
If you want to access the overridden method - which contradicts polymorphism - you can use reflection. Get the getLegs method from Animal's class, and then invoke it on your Kangaroo object. However, this is a hack, and not something you'd do in a regular program.
SOP( Animal.class.getMethod("getLegs").invoke(a) );

Related

What is significance of the term " hiding " in the method hiding concept in java? [duplicate]

This question already has answers here:
What is method hiding in Java? Even the JavaDoc explanation is confusing
(8 answers)
When is method hiding practically used?
(5 answers)
Closed 4 years ago.
The question has been put up to discuss around the term hiding which is associated with static methods in java.
Whenever a static method with the same signature is defined in the parent and the child class, the child class method is said to have hidden the method in the parent class. My question is around the usage of hiding, as we know static methods would be accessed by the class name or if we try to create a reference (which is a bad practice), method would be called based on the reference type. So how does hiding comes into picture, take example of below code:
public class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
}
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod(); // prints The static method in Animal
}
}
Can someone please explain how child method has hidden the parent method here? (parent method is being called using parent reference, so how does hiding comes into picture)
This demonstrates exactly why it's a bad practice to intend to hide a static method. The method is chosen statically, at compile time, without any consideration for the actual instance type.
I suppose the take home phrase should be "hiding is not overriding... and don't do it", to mean that Java doesn't even look at the object/instance (only looking at the declared type):
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testClassMethod(); //bad to do, but you can see it uses the declared "Animal" class
Cat.testClassMethod(); //Uses method in Cat
myCat.testClassMethod(); //Uses method in Cat
((Animal) null).testClassMethod(); //Uses Animal method, doesn't look at instance
((Cat) null).testClassMethod(); //Uses Cat method, doesn't look at instance
Now the interesting part: what if you remove the method from Cat?
All of these invocations will still work, using the Animal method, which means that:
It's a very bad practice to hide static methods
It's equally bad to use class instances to invoke static methods, because in the case of hidden methods, it's easy to be misled...
To answer the question: hiding is illustrated with Cat.testClassMethod() or myCat.testClassMethod(), which invokes the static method based on the declared type. When there's no testClassMethod() in Cat, Java calls the parent's.
How has the child method hidden the parent method here?
As you said, by defining a static method with the identical signature.
How does hiding comes into the picture?
Cat.testClassMethod();
Some may expect the invocation of the parent method here (by analogy with polymorphism). But the idea of hiding by class methods is different:
If a class C declares or inherits a static method m, then m is said to hide any method m', where the signature of m is a subsignature (§8.4.2) of the signature of m', in the superclasses and superinterfaces of C that would otherwise be accessible (§6.6) to code in C.
...
A hidden method can be accessed by using a qualified name or by using a method invocation expression (§15.12) that contains the keyword super or a cast to a superclass type.
...
class Super {
static String greeting() { return "Goodnight"; }
String name() { return "Richard"; }
}
class Sub extends Super {
static String greeting() { return "Hello"; }
String name() { return "Dick"; }
}
class Test {
public static void main(String[] args) {
Super s = new Sub();
System.out.println(s.greeting() + ", " + s.name()); // Goodnight, Dick
}
}
JLS 10 - 8.4.8.2. Hiding (by Class Methods)
This example is perfect to show the difference between overriding and hiding. At the same time, it is a bad practice demonstration - calling static methods on an instance.
I will try to make it clear by providing another example.
Since public static methods are inherited, the following snippet
class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
}
class Cat extends Animal {
public static void main(String[] args) {
// Cat: I don't have own method, probably I inherited it from the parent.
// O, yes. I can call it.
Cat.testClassMethod();
}
}
prints
The static method in Animal
Now we're going to add testClassMethod to Cat.
class Animal {
public static void testClassMethod() {
System.out.println("The static method in Animal");
}
}
class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The static method in Cat");
}
public static void main(String[] args) {
// Cat: I have two version of the method: mine and the inherited one.
// The caller specified my class name, so he wanted my version.
// I will call my method hiding the parent method.
Cat.testClassMethod();
// If he wanted Animal's version, he would write
Animal.testClassMethod();
// or (DON'T DO THIS)
((Animal)new Cat()).testClassMethod();
}
}
All final, static and private methods and variables use static binding and are bonded by compiler. Static binding uses Type information for binding (in this case Animal).
So, in your case myAnimal.testClassMethod(); will print the static method in Animal because declared type is Animal.
static methods don't take part in dynamic binding (polymorphism).
static methods aren't overritten, static methods are hidden by the subclass.
someone who calls Cat.testClassMethod() might expect the behaviour of Animal.testClassMethod()
So Cat.testClassMethod() is hiding Animal.testClassMethod()

How to change the super of a class?

I'll explain my issue in a code example. I have this static method called getNewBaby() (that I can not change) it only returns a Animal class. I need someway to convert that animal to Dog. Here's my two failed attempts so far:
public static class Animal
{
public void eat(){}
}
public static class Dog extends Animal
{
public Dog(Animal animal)
{
super = animal; // <-- error 1
}
public void bark(){}
}
.
public static Animal getNewBaby()
{
return new Animal( /* some future parameters */ );
}
public static void main()
{
//Attempt number 1:
Dog puppy1 = (Dog)(getNewBaby()); // <-- error 2
//Attempt number 2:
Dog puppy2 = new Dog(getNewBaby()); // <-- error 3
}
How can I fix this without changing anything in getNewBaby() method ?
What you are trying to do is impossible: you cannot re-initialize super.
However there are alternatives (assuming you cannot modify getNewBaby):
Enclose your down-casting in a try / catch statement and catch a ClassCastException
Use instanceof to check on the actual type, whether it's Animal, Dog, Cat, etc. and base your logic on that
Best choice declare methods in Animal that can be overridden on all child classes, thus de-coupling implementation
Edit
Here are a couple of additional topics - a bit off/broad, but might help you with your design.
Java inheritance and casting
The factory pattern in Java
Java generics
With the new information you have just posted as a comment (which really needs to be emphasized), here is a probably suitable solution for you.
This solution uses composition instead of inheritance. This means your custom class does not extend the original class, but contains an instance of it, and uses it internally.
I used to discourage you from using composition because of the Animal-Dog example, which was conceptually wrong, but here is a different use case, so a different answer ;-)
public class EasySocket {
private Socket socket;
public EasySocket(Socket socket) {
this.socket = socket;
}
/*
* Here are your helper methods that use socket's methods: for instance, use
* socket.getInputStream() instead of simply getInputStream(), since you don't inherit
* from the Socket class anymore.
*/
}
Then when you receive a Socket object:
Socket socket = someServerSocket.accept();
EasySocket easySocket = new EasySocket(socket);
// use easySocket
I can tell you why some things are wrong, but without more information about where you're going, we can't help you reorganize your code, though.
Bad constructor pattern
The following is just wrong with respect to inheritance:
public Dog(Animal animal) {
//...
}
Dog should not need an Animal to be created, because it Is-A Animal, which makes sense here.
Such a construct would be more in accordance to composition, but it wouldn't be appropriate here, and you would need to remove extends Animal on the Dog class.
Affectation of super
The following is not possible in Java because super is just a way of referring to this object as an object from the super class. You can't reaffect this either, because you are currently this object.
super = animal; // <-- error 1
About the cast fail
Casting an Animal to a Dog means that you know the object is indeed a Dog, and you want the compiler to assume it (cast is needed because of Java strong typing).
Here your getNewBaby() method returns an Animal object, not a subclass of it, so won't be able to cast it to Dog (ClassCastException at runtime) because it is simply an Animal (which does not make sense, by the way. Animal should be abstract).
Assuming that I understood your requirement correctly, you can do the following. Instead of trying to assign animal object to super, assign values in animal object to corresponding variables in Dog's super class.
public static class Animal
{
public Animal() {}
public int parameter1 =0;
public Animal(int param1){
this.parameter1 = param1;
}
public void eat(){}
}
public static class Dog extends Animal
{
public Dog(Animal animal) //This is not nice
{
super.parameter1 = animal.parameter1;
}
public void bark(){}
}
.
public static Animal getNewBaby()
{
return new Animal( 4 /*Some integer value for parameter1*/ );
}
public static void main()
{
Dog puppy2 = new Dog(getNewBaby());
}

Why do we need to override the methods of parent class?

I mean if we want to rewrite all the content of the method in the child class and change its function, why couldn't we just write a new method with a different name? What's the difference? I know this is a simple question. But I am new to programming and very confused. THX.
It's about giving different behaviour to common functionality for that type of thing, for example let's assume all Vehicles beep, but a Car Honk's and a Moped Meep Meeps!
class Vehicle {
public void beep() {
System.out.println("Beep!");
}
}
class Car extends Vehicle {
#Override
public void beep() {
System.out.println("Honk!");
}
}
class Moped extends Vehicle {
#Override
public void beep() {
System.out.println("Meep Meep!");
}
}
That's called Polymorphism. Have a look at the link.
A simple example is the Java Collections framework. You have an interface List when you are using it. You don't want to know how add or size is working. It should just work.
But when you are on the implementation side there are differences for ArrayList or a LinkedList in the way how they manage the items, that where stored in there.
When you look at already implemented methods in super classes, you might need one method to have a different behavior. Now pretend you have some method calls in your current code. If you don't want them to change, so you just override that method and the client does not have to change his code in order to use your functionality.
Overriding is a feature that is available while using Inheritance.
It is used when a class that extends from another class wants to use most of the feature of the parent class and wants to implement specific functionality in certain cases.
class Animal{
public void move(){
System.out.println("Animals can move");
}
}
class Dog extends Animal{
public void move(){
System.out.println("Dogs can walk and run");
}
}
class Cat extends Animal{
}
public class TestDog{
public static void main(String args[]){
Animal a = new Animal(); // Animal reference and object
Animal b = new Dog(); // Animal reference but Dog object
Animal c = new Cat(); // Animal reference but Cat object
a.move();// runs the method in Animal class
b.move();//Runs the method in Dog class
c.move();//Runs the method super method
}
}
So by using a parent class you dont need to define move() in each of class that extends animal you can override it wherever necessary.

How to wrap different type of object in one single wrapper object

i have a condition where i need to use a fixed Method signature which may accept different type of object. one solution i think is to use a super class and let all as a subclasses. however is there any good elegant design pattern kind of solution where we solve this
also once method gets an object of certain type can we know the type of instance without instanceof check ?
please suggest.
Your question is a little bit vaque, and can be interpreted in two different ways:
Implementing different behavior in one class
Let's assume you have two different classes: Cat and Dog. Then you have a class Animals and want to do something like this:
Cat cat = new Cat();
Dog dog = new Dog();
Animals animals = new Animals();
animals.feed(cat);
animals.feed(dog);
Here feed() executes different code, depending on the parameter type:
public class Animals {
public void feed(Cat cat) {
// ... feed the cat
}
public void feed(Dog dog) {
// ... feed the dog
}
}
This is called method overloading.
Implementing different behavior in different classes
On the other hand, you could define an interface Pet which provides a method, let's say eat():
public interface Pet {
void eat();
}
Then Cat and Dog should implement Pet to get different behavior:
public class Cat implements Pet {
public void eat() {
//...
}
}
public class Dog implements Pet {
public void eat() {
//...
}
}
Then your class Animals would look like this:
public class Animals {
public void feed(Pet pet) {
pet.eat();
}
}
Implementing an interface is a better pattern than inhering a super class. in that way your classes retain their one-inheritance capacity.
regarding the other question about instanceOf, there is rarely a genuine need to determine the actual class of the object. you can always resort to polymorphism. put all methods that you need to invoke on the object in the interface itself. in that way you will never need to know the actual type.

Clarity with method overriding

Was curious about the correct definition of the overridden method and the overriding method.
In my understanding the overriding method is the method in the subclass that overrides the method with same signature and return type in the base class.
I have however seen sources refer to the overridden method as being the method in the subclass that overrides the method in the base class.
So which is the overridden method and which is the overriding method?
Sorry if this is a bit of a silly question
Let's assume we have a class SubClass extends SuperClass, then:
SuperClass#method <- overridden
^
|
overrides
|
SubClass#method <- overriding
Apart from that, wikipedia tells us:
The implementation in the subclass overrides (replaces) the implementation in the superclass by providing a method that has same name, same parameters or signature, and same return type as the method in the parent class.
class A {
public void method() {
System.out.println("I don't know if I am overriden, but I'm not overriding anything");
}
}
class B extends A {
public void method() {
System.out.println("I am overriding A.method() which has now been overriden");
}
}
You can also read the section of the JLS that describes overriding, implementing, hiding, overloading etc. for more in depth understanding.
A direct example from the Java Documentation :
public class Animal {
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
public void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
public class Cat extends Animal {
public static void testClassMethod() {
System.out.println("The class method" + " in Cat.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
Animal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
The reason I used this example is, look at the scenario from your real-world situation. A Animal might have certain general features. But a Cat will have some features that are different from a generic Animal , but certain features that are an improvement over the generic Animal features. So, the Cat seems to override (will contain the overriding methods) the Animal features.
Another simple example if you are interested in cars. Say, there is a Car . It'll have an acceleration method. But a Ferrari will obviously have a better acceleration than a Car. But, a Ferrari is a Car. So, Ferrari overrides a method in Car. SO, overriding method is in subclass and the overriden method is in the base class.
So, do you get the point now? Overriding methods are present in the subclasses. But the methods that are overriden are present in the base class.

Categories

Resources