1

I am attempting to get a superclass method to run on subclass methods/fields when called by the subclass. For instance

public class CoffeeMachine() {
    protected int cost = 3;

    protected int getCost() {
        return cost;
    }
}

public class FancyCoffeeMachine() extends CoffeeMachine{
    protected int cost = 6;
}

main{
    FancyCoffeeMachine expensive = new FancyCoffeeMachine();
    System.out.println(expensive.getCost());
}

I would like this to print 6, but it prints 3 instead. I want to make this as DRY as possible, so I am trying to avoid making a second getCost() method. Is there any way to do this? How can I get a superclass method to use subclass variables, when called by the subclass? The same thing happens with methods: if I have

public class makeCoffee() {
    System.out.println("Coffee cost " + this.getCost());
}

the output will be "Coffee cost 3" even when I call makeCoffee on a FancyCoffeeMachine. Why is this? How can I fix it? Or is there a better way to implement this object structure that completely circumvents this mistake?

1
  • Your title doesn't agree with your question. You are asking about using overridden instance fields, not methods. Commented Feb 18, 2019 at 3:49

4 Answers 4

2

Linking fields does not use dynamic dispatch as virtual method calls do. Your field FancyCoffeeMachine.cost simply hides the field CoffeeMachine.cost.

To achieve what you want (i.e. FancyCoffeeMachine having a higher cost) you can simply set a new value to the CoffeeMachine.cost field within an initializer block or constructor in FancyCoffeeMachine.

public class CoffeeMachine {
    protected int cost = 3;

    protected int getCost() {
        return cost;
    }
}
public class FancyCoffeeMachine extends CoffeeMachine{
    {cost = 6;} // <- sets CoffeeMachine.cost
}
Sign up to request clarification or add additional context in comments.

Comments

0

You're calling method getCost from superclass(CoffeeMachine) because you don't have it in your subclass(FancyCoffeeMachine). And your superclass doesn't know anything about subclass and its field cost. You should also override method getCost to get it working like you described.

Comments

0

I am pretty sure you have to override getCost() on FancyCoffeeMachine too.

public class FancyCoffeeMachine() extends CoffeeMachine{
    protected int cost = 6;

    protected int getCost() {
        return cost;
    }
}

But If I wanted to implement this what I would do is make CoffeeMachine abstract like this

abstract class CoffeeMachine {
    private int cost;

    CoffeeMachine(int cost) {
        this.cost = cost;
    }

    int getCost() {
        return cost;
    }
}

and then extend it on my superclass like this

class FancyCoffeeMachine extends CoffeeMachine {
    FancyCoffeeMachine(int cost) {
        super(cost);
    }
}

and call it as such

FancyCoffeeMachine fancyCoffeeMachine =  new FancyCoffeeMachine(6);
System.out.println(fancyCoffeeMachine.getCost());

Comments

0

You wouldn't normally redefine a protected field like cost in a subclass. Instead, you would give the subclass a way to set the cost while constructing the object. Look at this:

public class Scratch {
    public static class CoffeeMachine {
        protected int cost;

        public CoffeeMachine() {
            this(3);
        }

        protected CoffeeMachine(int aCost) {
            cost = aCost;
        }

        public int getCost() {
            return cost;
        }
    }

    public static class FancyCoffeeMachine extends CoffeeMachine{
        public FancyCoffeeMachine() {
            super(6);
        }
    }

    public static void main(String[] args) {
        System.out.printf("plain: %d\n", new CoffeeMachine().getCost());
        System.out.printf("fancy: %d\n", new FancyCoffeeMachine().getCost());
    }
}

(Don't worry about the fact the two CoffeeMachine classes are declared static. That's just so they can all be defined in one file.)

The base class CoffeeMachine has two constructors:

  1. A protected constructor which accepts a cost as an argument.
  2. A public constructor which sets the cost to 3.

The subclass FancyCoffeeMachine calls the protected superclass constructor with a cost of 6. So the cost variable is set to 6 and getCost() will return that value when you run it:

plain: 3
fancy: 6

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.