简体   繁体   中英

Java - parent class is calling a method from a child class?

Sorry, I am still new to coding and may not have all the terminologies down. Hopefully, you will still understand my question. The output that I want to get is:

"Cost for Parent is: 77.77"
"Cost for Child is: 33.33"

However, I am getting this:

"Cost for Parent is: 33.33"
"Cost for Child is: 33.33"

Can anyone understand why? I have a simplified version of my code below but kept the logic behind it the same...

public class Parent{
    public double calculateCost(){
        return 77.77;
    }

    @Override
    public String toString(){
        return "Cost for Parent is: " + calculateCost();
    }
}

public class Child extends Parent{
    @Override
    public double calculateCost(){
        return 33.33;
    }

    @Override
    public String toString(){
        return super.toString() + "\nCost for Child is: " + calculateCost();
    }

    public static void main(String[] args){
        Child child1 = new Child();
        System.out.println(child1.toString());
    }
}

In my mind, the toString() in the Child class should be calling the toString() from the Parent class (thus, the calculateCost() from Parent class) then adding to it with a calculateCost() from Child. I'm guessing the super in super.toString() does not apply to calculateCost() that it contains.

Also, I know I can get around it by writing the toString() in the Child class like this:

    @Override
    public String toString(){
        return "Cost for Parent is: " + super.calculateCost() + "\nCost for Child is: " + calculateCost();
    }

but the point is that I don't want to repeat code and that I'd rather add to the previous toString() method that I am overriding. Please help or direct me (not sure what I should be googling for...) Thanks!

Please note that you are calling calculateCost() in toString method. Hence the child's calculateCost() is getting called. You consider using the Child's toString function as below.

class Parent{
public double calculateCost(){
    return 77.77;
}

@Override
public String toString(){

    return "Cost for Parent is: " + calculateCost();
}
}

class Child extends Parent{
@Override
public double calculateCost(){
    return 33.33;
}

@Override
public String toString(){
    return "Cost for Parent is: " + super.calculateCost() + "\nCost for 
Child is: " + calculateCost();
}
}

calculateCost is overriden in the Child class. Therefore when super.toString() is called from the Child , the calculateCost() in the super.toString() would be the Child 's calculateCost .

You have to put super.calculateCost() explicitly in the Child class to call the Parent 's calculateCost .

This is upcasting in java.
If subclass and parent class all have a method .then will execute the subclass. If not,then will excute the parent class, although you call the toString method including calculateCost

method which is in your parent class,but actually calculateCost method in the subclass will be exeuted.

You could modify your code as below:

Parent Class

public class Parent{
    public double calculateCostParent(){
        return 77.77;
    }


    public String toString(){
        return "Cost for Parent is: " + calculateCostParent();
    }
}

Child Class

public class Child extends Parent{

    public double calculateCost(){
        return 33.33;
    }

    @Override
    public String toString(){
        return super.toString() + "\nCost for Child is: " + this.calculateCost();
    }

    public static void main(String[] args){
        Child child1 = new Child();
        System.out.println(child1.toString());
    }
}

Output

Cost for Parent is: 77.77
Cost for Child is: 33.33

Then you could avoid the parent and subclasses has the same method of the same name at the same time.

You can depend on the best match for an overridden method to be called based on the actual type. In this case, you have an instance of a Child . Therefore, when you call an overridden method within overridden or non-overridden instance methods, you will see Child 's implementation. In other words,

Parent p = new Child();
System.out.println(p);

would give the same results.

I decided to put a private function prefixed with an underscore in my parent class in those cases to be able to target that specific function and still have the general public overridable function in my parent implementation.

public class Parent{
    public double calculateCost(){
        return _calculateCost();
    }

    // Add this parent specific implementation
    private double _calculateCost(){
        return 77.77;
    }

    @Override
    public String toString(){
        return "Cost for Parent is: " + _calculateCost();
    }
}

public class Child extends Parent{
    @Override
    public double calculateCost(){
        return 33.33;
    }

    @Override
    public String toString(){
        return super.toString() + "\nCost for Child is: " + calculateCost();
    }

    public static void main(String[] args){
        Child child1 = new Child();
        System.out.println(child1.toString());
    }
}

我认为这是 JVM 的行为,因为在 Java 中,每当我们调用对象上的方法时,该对象属于从其他类继承的类,JVM 会检查该方法是否被子类覆盖,因此尽管覆盖了子类的 toString() 方法,但对计算 cost() 的调用解析为子类的版本。

I think for this the best thing you could do is use a debug mode so you could better understand how it works. After reading your codes I understand how you want it to run.

But I think there is a problem with how you implement the @Override Annotation. The meaning of the

@Override annotation is to implement a new method that had been literally overriding from the parent class.

In this case, the public double calculateCost() of the Parent class will not be used since you Override the calculatecost for the Child class.

I hope I have explained it well. But on this case what you need to do is research more of the @Override and understand how it works.

Best you can do is to create a parent object, and a child object. Remove super.toString from child's toString method, then you will get the same results:

public class Parent{
    double cost = 77.77;
    public double calculateCost(){
        return cost;
    }

    @Override
    public String toString(){
        return "Cost for Parent is: " + this.calculateCost();
    }

}

public class Child extends Parent{
    @Override
    public double calculateCost(){
        return 33.33;
    }

    @Override
    public String toString(){
        return "\nCost for Child is: " + calculateCost();
    }

    public static void main(String[] args){
        Parent parent = new Parent();
        Child child1 = new Child();
        System.out.println(parent.toString() + child1.toString());
    }
}

Prints:

Cost for Parent is: 77.77
Cost for Child is: 33.33

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM