Why it always invokes parent class method "doTest(double d)"? [duplicate] - java

This question already has answers here:
Polymorphism in Overloaded and Overridden Methods
(4 answers)
Closed 6 years ago.
class PolymorphisomTest {
class Base {
public void doTest(double d) {
System.out.println("From Base");
}
}
class DerivedBase extends Base {
public void doTest(int d) {
System.out.println("From Derived Base");
}
}
public void use(Base base) {
base.doTest(3);
}
public void run() {
use(new Base());
use(new DerivedBase ());
}
public static void main(String []cmd) {
new PolymorphisomTest ().run();
}
}
Here doTest(double d) from parent class and doTest(int d) from subclass but when i call base.doTest(3) it always invokes parent class method even my object reference is different. what's the reason behind it?

doTest(double d) is a completely different method from void doTest(int d), because they have different parameter lists. There actually isn't any polymorphism there at all; DerivedBase is declaring a new method, not overloading Base.doTest. It's as if you had done this:
class Base {
public void doTest(double d) {
System.out.println("From Base");
}
}
class DerivedBase extends Base {
public void doSomethingElse(int d) {
System.out.println("From Derived Base");
}
}
Changing a parameter's type changes the method signature, and makes it a new method instead of overriding the parent class' method.
When you call base.doTest(3), the compiler is going to call doTest(double), because that's the only method of the Base class that matches the parameter. Because that method isn't overriden by anything, Base.doTest gets called.

To override a method you must match the method signature in the derived class. When you change from double to int you create a new method. From Defining Methods - The Java Tutorials,
Definition: Two of the components of a method declaration comprise the method signature—the method's name and the parameter types.
The #Override annotation can protect you from this specific class of error. You can do something like,
class DerivedBase extends Base {
#Override
public void doTest(double d) {
System.out.println("From Derived Base");
}
}

DerivedBase class inherited your doTest from base class. Now, it has 2 methods-
doTest (double d)
doTest (int d)
You have not overridden method but overloaded it by giving different parameter. If you need to override doTest add method with double as parameter.
Reason why it is not calling doTest (int d) is when we call from parent reference , it searches for method their during compile time and bind with same. And at runtime , its same method with same signature from object in hand.

Related

Why does calling a method from base class calls the child method?

I'm a student, learning Java. I know, protected means access from children or the same package. Here we inherit and override a protected method. And after such an action, whenever the base class wants to call its own method it calls the new overridden one from the subclass. I've been debugging this for a while and marked the execution order with comments. But I can't understand why doesn't it call the base method when I clearly call that from inside the base class constructor?
public class Solution {
public static void main(String[] args) {
new B(); // first
}
public static class A {
public A() {
initialize(); // third
}
protected void initialize() {
System.out.println("class A"); // we never go here
}
}
public static class B extends A {
public B() {
super(); // second
initialize(); // fifth
}
protected void initialize() {
System.out.println("class B"); // fourth, sixth
}
}
}
That's a task from one website, so basically the solution is to change access modifier of the initialize method from protected to private. But I still fail to understand why is the problem happening.
What you're trying to do is defeat the purpose of polymorphism. You can, but you have to make the call specifically. Add a Boolean to your method and call the super.initialize(Boolean). Again, this defeats polymorphism and the extending class HAS to know about the super class. NOT VERY ELEGANT.
public class Solution {
public static void main(String[] args) {
new B(); // first
}
public static class A {
public static boolean USE_SUPER = true;
public A() {
initialize(USE_SUPER);
}
protected void initialize(boolean unusedHere) {
System.out.println("class A");
}
}
public static class B extends A {
public static boolean USE_EXTENDED = false;
public B() {
super();
initialize(USE_EXTENDED);
}
protected void initialize(boolean useSuper) {
if (useSuper)
super.initialize(useSuper);
else
System.out.println("class B");
}
}
}
As Dakoda answered, the root cause is polymorphism. That means we may create child objects, but refer to them as their parent type and when we call the methods of the parent layer we actually refer to the child's methods.
In my case, I create a child object (marked //first) B, which has its own body of the initialize method. One nuance of the inheritance is that it doesn't include constructors, so I can call the parent's constructor (marked //second). Inside the parent's constructor, I call the initialize method - that is the polymorphism because I call the method of the child from its parent abstraction layer.
Here is the answer to the question - this happens, because we only allocated memory for a B instance, that means, we took A as our base and started to extend it (while we can overwrite anything inside). The only two things we did are:
We created a constructor (it wasn't included in the base, as mentioned above)
We overwrote the initialize method code. The code for this method that is inside the base is now lost for this object.
This concept of polymorphism is designed that way and there is no way for us to access the base method unless we specifically create an object that is either A itself or a child that doesn't overwrite this method.

Java Reflection get only methods of subclass (without equals, hashcode etc)

Is there a way to get the methods of an Class object, without getting the methods defined by the Object class?
Right now I am using getDeclaredMethods() to look for a specific method with a list of parameters.
My problem is that this also returns functions like
"equals", "hashCode", etc...
and thus it could be ambiguous between these functions and the one I'm looking for.
Looking at the documentation, it says that it only returns the public methods defined by this class (or in my case an interface), and my objects never override these methods
Is there any workaround for this?
Example:
class Test implements ITest {
void myMethod() {...}
}
and in my code I have something like
Object o = new Test();
for (Method m : o.getClass().getDeclaredMethods()) {
System.out.println(m.getName()...);
}
and this prints me methods defined in the Object class
getMethods()returns all methods declared by a class, plus methods declared in the object class. You can use getDeclaredMethods() to access methods that are class specific or implemented from super class. Example:
interface IChild {
int child1(int a, int b);
}
static class ChildImpl implements IChild {
#Override
public int child1(int a, int b) {
return a*b;
}
public int child2(int x, int y){
return x+x*y;
}
}
public static void main(String[] args) {
IChild i=new ChildImpl();
System.out.println("===Non Object Methods===");
for(Method m:i.getClass().getDeclaredMethods()){
System.out.println("Declared Method"+m.getName());
}
System.out.println("===All Methods===");
for(Method m:i.getClass().getMethods()){
System.out.println("Method: "+m.getName());
}
}
}
Sample output:
===Non Object Methods===
Declared Method: child2
Declared Method: child1
===All Methods===
Method: child2
Method: child1
Method: wait
Method: wait
Method: wait
Method: equals
Method: toString
Method: hashCode
Method: getClass
Method: notify
Method: notifyAll

toString,hashcode and equals method inside interface

Below example runs without any errors, can any one explain me how this works?, as interface doesn't contain any toString()/hashcode/equals method declaration how compiler will resolve method call?,as per my understanding toString()/hashcode/equals or Object class methods will be declared by default inside interface? please correct me if am wrong
interface int1
{
public void show();
}
class inttest implements int1
{
public void show()
{
System.out.println("inttest.show()");
}
#Override
public String toString()
{
return "tostring called";
}
}
public class MainClass1
{
public static void main(String[] args) {
int1 i=new inttest();
System.out.println(i.toString());
}
}
Any interface has all the public methods of the Object class (it either inherits them from a super-interface or declares them implicitly if it doesn't already declare them explicitly).
This makes sense, since any implementing class of any interface must be a (direct or in-direct) sub-class of the Object class, and therefore will inherit an implementation of all the Object methods.
9.2. Interface Members
If an interface has no direct superinterfaces, then the interface implicitly declares a public abstract member method m with signature s, return type r, and throws clause t corresponding to each public instance method m with signature s, return type r, and throws clause t declared in Object, unless an abstract method with the same signature, same return type, and a compatible throws clause is explicitly declared by the interface.
As all objects extend Object and Object has a toString() you are calling that method.

How to force my subclass constructor not to call base class constructor?

public class Base {
public Base() {
foo();
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived () {}
public void foo() {
System.out.println("Derived.foo()");
}
}
And then, when i call those:
public class Running {
public static void main(String[] args) {
Base b = new Base();
Derived d = new Derived();
}
}
It outputs:
*Base.foo()*
*Derived.foo()*
So why, when it gets to derived constructor, it invokes the base constructor but uses the derived's method instead?
PS: If I mark those methods as private, it will print out:
*Base.foo()*
*Base.foo()*
This is how Java works read this page https://docs.oracle.com/javase/tutorial/java/IandI/super.html
And more specifically the Note here :
Note: If a constructor does not explicitly invoke a superclass
constructor, the Java compiler automatically inserts a call to the
no-argument constructor of the superclass. If the super class does not
have a no-argument constructor, you will get a compile-time error.
Object does have such a constructor, so if Object is the only
superclass, there is no problem.
So as you can see this is expected behavior. Even though you dot have a super call it is still automatically inserting it.
In regards of the second Question even though you are within the super constructor body still you Instance is of the Subtype. Also if you have some familiarity with C++ read this Can you write virtual functions / methods in Java?
The reason why it will write the base class when marking with private is because private methods are not Inherited. This is part of the Inheritance in Java topic.
To answer the question in your title. As I said, you cannot avoid the base class constructor being called (or one of the base class constructors if it has more than one). You can of course easily avoid the body of the constructor being executed. For example like this:
public class Base {
public Base(boolean executeConstructorBody) {
if (executeConstructorBody) {
foo();
}
}
public void foo() {
System.out.println("Base.foo()");
}
}
public class Derived extends Base {
public Derived() {
super(false);
}
public void foo() {
System.out.println("Derived.foo()");
}
}
public class Running {
public static void main(String[] args) {
Base b = new Base(true);
Derived d = new Derived();
}
}
Now the main method prints only:
Base.foo()
Because in the contructor of the Derived class it automatically gets injected a call to super(), if you do not add a call to super or to other constructor in the same class (using this).

Can I override using subclass object as parameter in Java?

I have classes as follows
public class Useful
{
public void f(Object a)
{
System.out.println("In base f");
}
public void g(String a)
{
System.out.println("In base g");
}
}
public class MoreUseful extends Useful
{
public void f(String a)
{
System.out.println("In derived f");
}
public void g(Object a)
{
System.out.println("In derived g");
}
}
I am trying to override base class method but I am changing the parameters in derived class.
in method MoreUseful.f() I am using subclass parameter (String) as against Object in base class.
in method MoreUseful.g() I am using superclass parameter (Object) as against String in base class.
Is it possible to override these way?
Which of the above two cases will be correct overriding?
No, that's not possible, and would be a violation of the LSP.
By inheriting from a class, you express that your subclass MoreUseful is actually a Useful and therefore exposes all the functionality that Useful exposes. If you removed the ability to invoke f with an object, you'd break that promise.
You are free to overload f so that you have an f(String s) method though.
The g() method is indeed overriden. f(), however, is not overriden - it's overloaded. An easy way to verify this is to add #Override on each method you intend to override - if it results in a compilation error, you aren't overriding properly.

Categories

Resources