I have the following classes :
public abstract class Animal
{
private String species;
public Animal(String ll)
{
species = ll;
}
public abstract void speak();
public String toString()
{
return "Species: " + species;
}
}
The 2nd class:
public class Raven extends Animal
{
String name;
public Raven(String emri)
{
super("Raven");
name = emri;
}
public void speak()
{
System.out.println("krra krra");
}
public String toString()
{
return super.toString() + "\nName : "+ name ;
}
}
and the test class :
public class TestAnimals
{
public static void main(String args[])
{
Raven blabla = new Raven("Ziosh");
Animal a = blabla;
System.out.println(a.toString());
}
}
When I execute the test class, I get :
Species: Raven
Name: Ziosh
What I don't understand is why does Java use the "new" toString() method, even after we "upcast" the Raven object to Animal ?
Thanks.
Because that's what polymorphism is all about: you can call a method of an object without knowing the actual concrete type of the object, and the appropriate method, defined in this concrete type, will be called.
This works exactly like real objects: if I give you a car, even if you don't know it's actually a hybrid car, the car will behave like a hybrid car when you drive it.
In your example, a and blabla are two references to the same object, which is a Raven instance. So this object *speak*s and *toString*s like a Raven.
When you call a method in java, even if it's cast to the super type, it always looks for the most overridden method to call.
From http://docs.oracle.com/javase/tutorial/java/IandI/override.html
The distinction between hiding a static method and overriding an instance method has important implications:
The version of the overridden instance method that gets invoked is the one in the subclass.
The version of the hidden static method that gets invoked depends on whether it is invoked from the superclass or the subclass.
Raven blabla = new Raven("Ziosh");
Animal a = blabla;
Here, a and blabla reference the exact same object, as you can confirm with:
System.out.println(a == blabla);
// prints "true"
As such, a is really a Raven, so naturally it will talk like a Raven, even if you label it an Animal.
Consider another explanation in human terms. Letting the implementation to be executed on an object of a subclass could be actually very dangerous. Imagine a Bicycle class, and its more specialized BicycleWithLittleWheels. The thing about the latter, the little wheels are quite fragile, and if you try to ride it too fast, they could break. If you let somebody ride that bicycle as if was a regular bicycle, completely obvious of the little wheels, he may break it. By similar logic, you probably shouldn't use a high-precision dental drill the same way as a sledgehammer.
This is why, intuitively, you shouldn't let a specialized object be treated as its more general form. Sure, in some cases, it may make sense to use a specialized object as if it was something more general, but not always. How could the compiler distinguish the safe cases from the unsafe cases? That would be too difficult. So to stay on the safe side, the language won't let you do this.
Java always uses the method of the instance as describe in this post:
java override method invocation
Related
What does it mean by "Casting affects the selection of overloaded methods at compile time but not overridden methods"?
I read the following passage on "Overridden methods and dynamic binding" (https://www.oreilly.com/library/view/learning-java-4th/9781449372477/ch06s01.html) and I couldn't understand the last paragraph
"In a previous section, we mentioned that overloaded methods are selected by the compiler at compile time. Overridden methods, on the other hand, are selected dynamically at runtime. Even if we create an instance of a subclass our code has never seen before (perhaps a new class loaded over the network), any overriding methods that it contains are located and used at runtime, replacing those that existed when we last compiled our code.
In contrast, if we created a new class that implements an additional, more specific, overloaded method, and replace the compiled class in our classpath with it, our code would continue to use the implementation it discovered originally. This situation would persist until we recompiled our code along with the new class. Another effect of this is that casting (i.e., explicitly telling the compiler to treat an object as one of its assignable types) affects the selection of overloaded methods at compile time but not overridden methods."
I couldnt understand the "Casting" line: "Another effect of this is that casting (i.e., explicitly telling the compiler to treat an object as one of its assignable types) affects the selection of overloaded methods at compile time but not overridden methods."
That line is referring to the fact that
overloaded versions of a method are chosen at compile time, based on the compile-time types of the arguments that you are passing; whereas
overridden methods are chosen at run time, based on the classes of the objects on which you call each method.
To understand this distinction, consider a situation where you have both overrides and overloads, like this.
public class Person {
}
---------------------------------------------------------
public class Postman extends Person {
}
---------------------------------------------------------
public class Dog {
public void barkAt(Person p) {
System.out.println("Woof woof");
}
public void barkAt(Postman p) {
System.out.println("Grrrr");
}
}
---------------------------------------------------------
public class Rottweiler extends Dog {
#Override
public void barkAt(Person p) {
System.out.println("I'm going to eat you.");
}
#Override
public void barkAt(Postman p) {
System.out.println("I'm going to rip you apart.");
}
}
In this situation, we call one of these barkAt methods, like this.
Dog cujo = new Rottweiler();
Person pat = new Postman();
cujo.barkAt(pat);
Now in this particular case, it's the compiler that chooses whether cujo.barkAt(pat); calls a method like public void barkAt(Person p) or public void barkAt(Postman p). These methods are overloads of one another.
To do this, the compiler looks at the type of the expression being passed to the method - that is, the variable pat. The variable pat is of type Person, so the compiler chooses the method public void barkAt(Person p).
What the compiler doesn't do is choose whether it's the method from the Rottweiler class or the Dog class that gets called. That happens at run time, based on the class of the object on which the method gets called, NOT on the type of the variable that you call the method on.
So in this case, what matters is the class of the object called cujo. And in this example, cujo is a Rottweiler, so we get the overridden version of the method - the one defined in the Rottweiler class.
This example will print out I'm going to eat you.
To summarise:
The overload is chosen at compile time based on the parameter type.
The override is chosen at run time based on the object class.
Now, it's possible to use casting to change the compiler's choice of overload. It's not possible to use casting to change the run time choice of override. So, we could write
cujo.barkAt((Postman) pat);
This time, the parameter passed to the method is an expression of type Postman. The compiler chooses an overload accordingly, and this will print I'm going to rip you apart..
Casting affects the selection of overloaded methods at compile time but not overridden methods
Overloaded methods are visible at compile time. But overridden methods becomes visible at runtime.
Thumb Rule:
Java calls the overridden methods based on contents of reference variable and not type of reference variables.
Below example is self explainatory. Hope it helps.
class Animal {
public void speak() {
System.out.print("Animal sounds/roars.");
}
}
class Human extends Animal {
#Override // Method is overridden
public void speak() {
System.out.print("Humans talking english.");
}
public void speak(String words) { // Method is overloaded.
System.out.print("We have brain. We are intelligent."+words);
}
}
class Earth {
public static void main(String a[]) {
Animal a = new Animal();
a.speak(); // Prints Animal sounds/roars.
Human h = new Human();
h.speak(); // Prints "Humans talking english."
Animal a = h; // Cast to superclass reference variable. However, underlying object is of Human.
a.speak(); // Prints "Humans talking english." because speak() is known by Animal at compile time. During runtime,
// the object contains the human object and hence java calls human overridden method.
a.speak("I want to be human."); // Compile time error as speak(..) is not known by Animal at compile time.
}
}
Hello guys I have question related to 'this' keyword in Java.
(1)
Lets say Computer extends from Machine and we have the current code:
public class Machine {
private String name = "Machine";
public void test()
{
System.out.println(this.name);
}
public void test2()
{
System.out.println(this);
}
}
public class Computer extends Machine {
public void test()
{
System.out.println(this);
}
}
public class main {
public static void main(String[] args) {
Machine c = new Computer();
c.test();
c.test2();
}
}
Its prints:
Computer#1db9742
Computer#1db9742
It means the 'this' in Computer refers to Computer and this is I understood but the 'this' in Machine also refers to Computer and this is what I didn't understand.
How this happened and why..???
(2)
So if Machine m = new Computer() this is true?
So to all that answered me, i can understand that this is related to the new or what we say what our Type pointing for...?
The keyword this refers to the current object, that is an instance of a class, not to a class itself. You have created a single object (with new Computer()), which is an instance of Computer. Since Computer is a subclass of Machine, it is also an instance of Machine, but the default toString() method will return a string containing the most precise type, in this case Computer.
Computer#1db9742 is just a name for your object. It is the same object, even if each method is defined in a different class.
"this" refers to the object, not to the class.
Computer extends Machine, so Computer inherits all the methods of Machine, making them their own.
When you instantiate Computer you're running all of it's methods.
You cannot access private variables from the class, you have to either create getter method or make the variable public, moreover this in System.out.println() calls toString() method, and if undefined, it prints something like that you have in results (type of object and location in memory).
Just create method in Machine class:
public String getName() {
return name;
}
And in main method make add following:
System.out.println(c.getName());
It's the instanciated type that counts. Not the reference.
Take this example:
class Animal{
void makeSound(){
System.out.println("wut ? Don't know what to do :(");
}
}
class Cat extends Animal{
void makeSound(){
System.out.println("Miaw !");
}
}
when you create for example:
Animal a = new Cat();
You're actually creating a cat. And still, a Cat is always an animal ? (Am I right ? :D)
a.makeSound() will result in printing Miaw !. But !
Animal a= new Animal();
a.makeSound();
will result in printing : wut ? Don't know what to do :( . What's the sound of an animal after all ? You see ?
If someone asks you to bring an animal, you can always bring a cat. Right ?
Well, this is the case with methods asking for an Animal parameter:
take this function:
void doSomething(Animal param){
// some code
}
you can call it using a Cat object as a parameter:
//...
doSomething(new Cat());
//...
Etc.. (you can push the analogy.. for a wider level)
Java VM takes the responsibility to make a type resolution at run time to decide which method to call. And that's some of the sweetness of OOP.
this is a pointer to the current object, and objects know what type they are.
this references the context that you are in. In your case, you are using it on the Machine and the Computer class.
To understand this, you need to first understand that the variable Machine m, is not the object itself, but it does reference to the object in the memory.
An then, you are calling from the same object, two different methods, one that is implemented on the objects class(Computer), and other that is implemented on its superclass(Machine).
Indifferently witch method is called, the object where you make the method call is the same, and the this keyword, will reference this same object, and then, the result of your test will be exactly the same object:
Computer#1db9742
Computer#1db9742
Imagine I have this:
public class Animal {
private String racaAnimal;
private String corAnimal;
public String getCorAnimal() {
return this.corAnimal;
}
public String getRacaAnimal() {
return this.racaAnimal;
}
public Animal getAnimaisCliente(int indice) {
return this.animaisCliente[indice];
}
}
public class Estimacao extends Animal{
private String nomeAnimal;
public String getNomeAnimal() {
return nomeAnimal;
}
}
public class Cliente{
private Animal[] animaisCliente;
}
Constructors aren't showing but they are working fine.
I have one arraylist that holds all Cliente
ArrayList<Cliente> clientes = new ArrayList<Cliente>();
And a animal is created like this
Estimacao animaisEstimacao = new Estimacao(nomeAnimal,racaAnimal,corAnimal);
and then its added to the array of Animal in Cliente
Now if I do this:
System.out.println(" Raça: " + clientes.get(0).getAnimaisCliente(0).getRacaAnimal());
It works.
But how can i get nomeAnimal from class Estimacao?
If i put
System.out.println(" Nome: " + clientes.get(0).getAnimaisCliente(0).getNomeAnimal());
it do not works.
From a subclass we can get things from the super class but the other way arroud? is it possible?
You need to cast your Animal to Estimacao. But obviously, if you don't want to risk an exception, make sure your Animal is of the right class before:
Animal animal = clientes.get(0).getAnimaisCliente(0);
if (animal instanceof Estimacao) {
System.out.println(" Nome: " + ((Estimacao) animal).getNomeAnimal());
}
Think of it this way: an instance of a subclass is also an instance of the superclass. But an instance of the superclass is not necessarily an instance of the subclass. Thus the superclass methods are always available in both, but the subclass methods are only available in the subclass.
If you are sure you have an instance of the subclass, you can cast it explicitly and call the subclass-specific method on it, but you need to take care in doing so.
Try
System.out.println(" Nome: " + ((Estimacao) clientes.get(0).getAnimaisCliente(0)).getNomeAnimal());
In addition to the answers provided above, you may want to just consider the general design of your classes. If the nomeAnimal is something that the Animal class should really be aware of then it might make sense to push it up (even the name of the variable suggests its Animal-ness).
If not, then you may want to further consider leveraging polymorphism by adding a displaySpecificInfo() to the Animal class and either making it abstract, or adding an empty implementation in the Animal class. That would allow you to call it from where your current - failing - print call is, and then have the current line in the derived class's implementation. This would save the need for the cast (not that there's anything wrong with casting), as well as create a more OO/Encapsulation-compliant implementation.
Edit:
Excellent note by #Guillaume and my apologies for potentially peeling back more layers of the OO onion then you are interested in! :)
Cast the Animal to a Estimacao to access the methods defined in Estimacao
It is not possible directly as you are asking. However, you could add getNomeAnimal() in your base class (Animal), that would return null or an empty string - then the instances which are of Estimacao class will return the correct values.
This is a misplaces usage in your animal class:
this.animaisCliente[indice] // animaisCliente is not an attribute of Animal
No you can't do it unless you cast the Animal type object to Estimacao type. Only after the cast, the getNomeAnimal() will be available to you. But this is a bad thing to do. If your array contains a mix of Animal type and Estimacao type objects then it will fail with ClassCastException.
I give lessons on the fundamentals of the Java programming language, to students who study this subject in college.
Today one of them got me really confused with her question, so I told her to give me just a day to think about the problem, and I'll give her as accurate of an answer as I can.
She told me that the teacher got really angry when she used the keyword instanceof in her exam.
Also, she said that the teacher said that there is not a way to prove how polymorphism worked if she used that word.
I thought a lot to try to find a way to prove that in some occasions we need to use instanceof, and also that even if we use it, there still some polymorphism in that approach.
So this is the example I made:
public interface Animal
{
public void talk();
}
class Dog implements Animal {
public void talk() {
System.out.println("Woof!");
}
}
public class Cat implements Animal
{
public void talk() {
System.out.println("Meow!");
}
public void climbToATree() {
System.out.println("Hop, the cat just cimbed to the tree");
}
}
class Hippopotamus implements Animal {
public void talk() {
System.out.println("Roar!");
}
}
public class Main {
public static void main(String[] args) {
//APPROACH 1
makeItTalk(new Cat());
makeItTalk(new Dog());
makeItTalk(new Hippopotamus());
//APPROACH 2
makeItClimbToATree(new Cat());
makeItClimbToATree(new Hippopotamus());
}
public static void makeItTalk(Animal animal) {
animal.talk();
}
public static void makeItClimbToATree(Animal animal) {
if(animal instanceof Cat) {
((Cat)animal).climbToATree();
}
else {
System.err.println("That animal cannot climb to a tree");
}
}
}
My conclusions are the following:
The first approach (APPROACH 1) is a simple demo of how to program to an interface, not a realization. I think that the polymorphism is clearly visible, in the parameters of the method makeItTalk(Animal animal), and also in the way the method talk is called, by using the animal object.(This part is ok)
The second part is the one that makes me confused. She used instanceof at some point in her exam (I don't know how their exam looked like), and that was not accepted correctly because the teacher said, you are not proving polymorphism.
To help her understand when she can use instanceof, I thought about telling her, that she can use it, when the method she needs to call is not in the interface, but it is just in one of the implementing classes.
As you can see, only cats can climb to trees, and it would not be logical to make a Hippopotamus or a Dog climb to a tree. I think that could be an example of when to use instanceof
But what about polymorphism in approach 2?
How many uses of polymorphism do you see there (only approach 2)?
Do you think this line has some type of polymorphism in it?
((Cat)animal).climbToATree();
I think it does, because in order to achieve a Casting of this type, the objects need to have an IS-A relationship, an in some way that is polymorphism.
What do you think, is it correct?
If yes, how would you explain with your own words, that casting relies on polymorphism?
The reason the instanceof method is seen as bad is simple. Cats aren't the only Animal that might be able to climb a tree.
What happens if down the road you need to add a Koala class. Then your simple if becomes a not so simple or. Then, what happens when you add another class? and another one. And another one. That's the prime reason why instanceof is seen as bad. Because it couples the implementation to a concrete class, rather than opening it for the callee to determine what to do.
Simply implement the makeItClimbToATree() method to throw a CantClimbTreesException if called on an animal that can't climb. That way you have the best of both worlds. Easy to implement, and easy to extend.
IMHO, instanceof has only 1 truly valid use: In a test case to test the returned instance from a method matches the expected return type (in non-type safe languages).
Basically any other use can more than likely be refactored away or designed differently to negate the need for its use.
Another way to look at it is this: Polymorphism allows you to eliminate almost all conditional statements from your code. The only conditionals that you can't get rid of (at least all of them) are in object creational methods (such as in a factory where it must choose the class based upon a runtime argument). Just about any other conditional can be replaced by polymorphism. Therefore, anything that does conditional execution is by definition anti-polymorphic. That's not to say it's bad (there's a huge difference between Good and Good Enough), But in an academic discussion, it's not polymorphic...
Never forget the 60/60 rule. 60% of your total development time will be spent maintaining the code you wrote, and 60% of that time will be spent adding new features. Make maintaining easier, and your life will be easier as well. That's why instanceof is bad. It makes the initial design easier, but complicates the long term maintenance (which is more expensive anyway)...
In your above example, there is no need to call
makeItClimbToATree (new Hippopotamus ());
It could be easily avoided, if makeItClimbToATree wouldn't expect an animal, but something more specific, which is really able to climb a tree. The necessity to allow animals, and therefore to use instanceof, isn't visible. If you manage the animals in a List of animals, it will be more obvious.
While ircmaxells explanation starts great, while introducing the Koala and other TreeClimbers, he doesn't see a second extension which is hiding in a sea anemone: different capabilities of animals like seaAnemoneHider, winterSleeping, blueEyed, bugEating, and so on, and so on. You would end up with boolean over boolean, constantly recompiling the base class, as well as breaking extending customer classes, which would need recompilation again, and wouldn't be able to introduce their own possibilities in a similar manner.
Customer A would need Customer B to declare a NotBugEatingException, to get your behaviour into the base class.
Introducing your own interfaces, combined with instanceof, is a much cleaner approach, and more flexible. Customer A might define divingLikeAPenguin and customer B trumpeting, both not knowing of each other, both not affecting the Animal class and not provoking useless recompilations.
import java.util.*;
interface Animal {
public void talk ();
}
interface TreeClimbing {
public void climbToATree ();
}
class Dog implements Animal {
public void talk () { System.out.println("Woof!"); }
}
class Cat implements Animal, TreeClimbing {
public void talk () { System.out.println("Meow!"); }
public void climbToATree () { System.out.println ("on top!"); }
}
public class TreeCriterion {
public static void main(String[] args) {
List <Animal> animals = new ArrayList <Animal> ();
animals.add (new Cat ());
animals.add (new Dog ());
discuss (animals);
upTheTree (animals);
}
public static void discuss (List <Animal> animals) {
for (Animal a : animals)
a.talk ();
}
public static void upTheTree (List <Animal> animals) {
for (Animal a : animals) {
if (a instanceof TreeClimbing)
((TreeClimbing) a).climbToATree ();
}
}
}
We don't need a third animal, dog and cat are enough. I made them default visible instead of public, to make the whole example fit into a single file.
Do you think this line has some type of polymorphism in it?
((Cat)animal).climbToATree();
No. Especially, since Cat is a leaf class in the example.
I think it does, because in order to achieve a Casting of this type, the objects need to have an IS-A relationship, an in some way that is polymorphism.
Polymorphism requires the IS-A relationship, but not the other way round.
Polymorphism is when you dispatch to (potentially) different methods based on an abstract interface. If you don't have that dispatching, then it is not using polymorphism. In your example, using instanceof to cast to a class with no subclasses, you are removing the need for dispatching.
(Of course, there is more than one way to "do polymorphism" in Java. You can implement it using interfaces, using abstract classes, or using concrete classes with subclasses ... or hypothetical subclasses that may be written in the future. Interfaces (and dispatching based on an interface) are generally the best way because they give a clean separation of the API from the identity of class.)
And on a separate note, using instanceof like that is typically a sign of poor design and / or poor modelling. Specifically, it hard-wires the assumption that only cats can climb, which is trivially falsified if we include other animals into the model / program. If that happens, your code breaks.
Maybe I'm missing the point and don't get the context of the exam question, but whether an Animal can climb a tree should be a part of the class that implements Animal. For example, if Animal is an interface, you could have a method boolean isCapableOfClimbing() and then each implementing class would be able to indicate its capability.
A method that attempted to make the animal climb could then use that. It doesn't make sense for a method that's trying to make the animal climb a tree check whether it's an instance of a particular class, since then that method is specifying something that should be specified in the implementing class. A simple method should not provide behaviour for a class that it's using.
As for your question of when to use instanceof, once place where it will almost always be used is if overriding the equals() method of a class, since it only accepts an Object and you typically have to ensure it is of the same type so it can be cast and then meaningfully compared.
What about something like the code below? It solves the generality problem by separating the tree-climbing as another interface you can implement or not on your animals. It fits the problem better: climbing trees is not an intrinsic property of all animals, only of a subset of them. At least to me it looks much clearer and elegant than throwing NotImplementedExceptions.
public interface Animal {
public void talk();
}
public interface AnimalCanClimbTrees extends Animal {
public void climbToATree();
}
public class Dog implements Animal {
public void talk() {
System.out.println("Woof!");
}
}
/* Animal is probably not needed, but being explicit is never bad */
public class Cat implements Animal, AnimalCanClimbTrees
{
public void talk() {
System.out.println("Meow!");
}
public void climbToATree() {
System.out.println("Hop, the cat just cimbed to the tree");
}
}
class Hippopotamus implements Animal {
public void talk() {
System.out.println("Roar!");
}
}
public class Main {
public static void main(String[] args) {
//APPROACH 1
makeItTalk(new Cat());
makeItTalk(new Dog());
makeItTalk(new Hippopotamus());
//APPROACH 2
makeItClimbToATree(new Cat());
makeItClimbToATree(new Hippopotamus());
}
public static void makeItTalk(Animal animal) {
animal.talk();
}
public static void makeItClimbToATree(Animal animal) {
if(animal instanceof AnimalCanClimbTrees) {
((AnimalCanClimbTrees)animal).climbToATree();
}
else {
System.err.println("That animal cannot climb to a tree");
}
}
}
The instanceof operator has nothing to do with polymorphism. It is simply used to see whether or not an object is an instance of a particular class. You see this operator being used a lot in the equals() method, because the method takes a generic Object as a parameter:
public class Cat implements Animal{
#Override
public boolean equals(Object obj){
if (obj == null || !obj instanceof Cat){
//obj is null or not a "Cat", so can't be equal
return false;
}
if (this == obj){
//it's the same instance so it must be equal
return true;
}
Cat catObj = (Cat)obj; //cast to "Cat"
return this.getName().equals(catObj.getName()); //compare the two objects
}
}
If a class does not implement a method, then it should throw an exception. I believe the "official" exception you are supposed to throw is UnsupportedOperationException. To be "correct", I think the Animal interface should have a public void climbToATree(); method. The climbToATree() methods in the Dog and Hippo classes should throw an UnsupportedOperationException because they cannot implement this method. But if you are throwing this exception very often, then there may be something wrong with your object model, as this is not a common thing to do I don't think.
Also note that it's helpful (but not required) to use the #Override annotation with polymorphic programming in Java. This will cause a compilation error to be thrown if a method with this annotation does not override a parent method, implement an abstract method, or (in Java 6) implement an interface method. This can help catch any mistakes you make in the method signature. For example:
public String tostring(){
return "foobar";
}
Without the annotation, the program would compile and run successfully. But this was not your intention! You wanted to override toString(), but you accidentally spelled the name wrong!!
I'm surprised no one wrote anything about Late Binding. Polymorphism in Java = Late Binding. The method being called will be be attached to the object when we finally know its type. In your example:
if(animal instanceof Cat) {
((Cat)animal).climbToATree();
}
You are calling climbToATree() on a Cat object so the compiler accepts it. At run time, there is no need to check the type of the calling object since climbToATree() belongs to Cat only. And so there is no polymorphism in these lines of code.
About casting being related to Polymorphism, it isn't. Casting just limits the fields that are shared in both objects, if the cast is legal. You could do this:
class A {
int getInt() {}
}
class B extends A {
int getInt() {}
}
// in main
A a = new B();
A b = (A)a;
b.getInt(); // This would still call class B's getInt();
The cast itself added no value, getInt() was bound at run time to the runtime type of a, which was class B.
A polymorphic and OOP approach would be to place the method makeItClimbToATree on the Animal interface:
public interface Animal{
public void talk();
public void makeItClimbToATree();
}
Then the implementors of Animal would provide the behavior for the method, which for all other than Cat could be to throw an exception. This is polymorphic because you operate on different implementations of Animal through a single method.
The function which uses the instanceOf operator is considered "bad" OOP because it requires knowledge of all the implementation types to determine the behavior of the method.
class Super {
public void anotherMethod(String s) {
retValue(s)
}
public String retValue(String s) {
return "Super " + s;
}
}
class Sub extends Super {
public void anotherMethod(String s) {
retValue(s)
}
public String retValue(String s) {
return "Sub " + s;
}
}
if suppose in main,
Super s = new Sub();
s.anotherMethod("Test");
Output will be, Sub Test
Can you anyone help me in telling how to get output Super Test with the given sequences in main.
And let me explain why I want this, say I have a class which has method test() and it can be overriden by sub classes, in some cases I want the overriden test() and in some cases I want the test() of super class itself, there are many ways to do this, best suggestions will be helpful.
Why would you ever want to do that ??
The whole point of polymorphism is to call the right method without the need to know which kind of instance you've got ...
Whenever I find myself asking (or being asked) a question like this, I know, categorically, that I have made a mistake in my design and/or my object definitions. Go back to your object hierarchy and check, double-check and triple-check that every inheritance relationship represents an "IS-A", and not a "HAS-A" or something even weaker.
And let me explain why I want this,
say I have a class which has method
test() and it's can be overriden by
sub classes, some cases I want the
overriden test() and in some cases
test() of super class itself, there
are many ways to do this, it will be
helpful if anyone can be best
solution.
If your subclass overrides test(), then it overrides test() - this is the whole point of object inheritance. You just call methods on the object, which are dynamically resolved to the appropriate implementation based on the object's runtime class. That's the beauty of polymorphic typing, in fact, the caller doesn't have to know about any of this at all, and the subclasses determine how their behaviour differs from the superclass.
If you sometimes want it to act as its superclass method and sometimes want it to act as its subclass method, then you need to provide the context required to do this. You could either define two test-type methods; one which is never overridden and so always returns the superclass' behaviour (you can even mark the definition with final to ensure it's not overridden), and your normal one which is overridden as appropriate by the subclasses.
Alternatively, if there is some contextual information available, you can let the subclasses decide how to handle this; their implementation(s) could check some proeprty, for example, and based on that decide whether to call super.test() or proceed with their own overridden implementation.
Which one you choose depends on conceptually whether your main method (i.e. the caller), or the (sub)class objects themselves, are going to be in the best position to judge whether the superclass' method should be called or not.
But in no case can you override a method and expect it to magically sometimes not be overridden.
You would have to go the route of:
Super s = new Super();
s.anotherMethod("Test");
...but that will defeat the purpose of inheritance if you also need whatever Sub's got. You could hack it like below but this seems an unelegant way to do it.
class Sub extends Super {
public String anotherMethod( String s, boolean bSuper ) {
if( bSuper )
return super.retValue(s);
else
return retValue(s);
}
public String retValue(String s) {
return "Sub " + s;
}
}
From class Sub you can call super.anotherMethod("bla"), but you cannot access the method of the superclass in your main method - that would be against the whole idea of using subclasses.
The runtime type of s is Sub, so you're only ever calling methods on that class.
Whilst I agree with the other posters that this is not the best idea in the world, I believe it could be done with a little bit of tinkering.
If your child class was defined as:
class Sub extends Super {
public void anotherMethod(String s) {
retValue(s)
}
public void yetAnotherMethodString s) {
super.retValue(s)
}
public String retValue(String s) {
return "Sub " + s;
}
}
and then call this new method in your main you would be able to print out "Super Test".
Doesn't seem like a very good plan tho. If you want access to parent functionality from a child class then don't override your parent method, just write a new one!
I'm hesistant to post this as an answer, since the question is quite horrible - but static methods would do roughly what the OP seems to want. Specifically, they are resolved on the compile-time declared class of the variable, not on the class of the instance held within that variable at runtime.
So modifying the original example:
class Super {
public static void staticMethod(String s) {
System.out.println("Super " + s);
}
}
class Sub extends Super {
public static void staticMethod(String s) {
System.out.println("Sub " + s);
}
}
public static void main(String[] args) {
Super s = new Sub();
s.staticMethod("Test");
}
then main() will print out "Super test".
But still don't do this until you understand why you want to, and you recognise that you are introducing subclasses and then gratuitously working around the point of them being there. Most IDEs for example will flag the above example with lots of warnings, saying that you shouldn't call static methods on instance variables (i.e. prefer Super.staticMethod("Test") instead of s.staticMethod("Test")), for exactly this reason.
You cannot modify Sub or Super directly? If you could control what instance of Sub is used you could do something like:
Super sub = new Sub() {
#Override
public String retValue() {
// re-implement Super.retValue()
}
};
otherObject.use(sub);
Of course this requires you to have or be able to reproduce the source code of Super.retValue() and for this method not to use anything you can't access from an anonymous child. If the API is this badly designed though, you might do well to think about changing it out for something else.
Can you anyone help me in telling how
to get output "Super Test" with the
given sequences in main.
Don't overwrite anotherMethod() and retValue() in Sub in the first place.
In Sub.anotherMethod(), return super.retValue(s) instead of retValue(s).