Java получает метод суперкласса для использования метода экземпляра подкласса при вызове подклассом - PullRequest
0 голосов
/ 17 февраля 2019

Я пытаюсь заставить метод суперкласса запускаться на методах / полях подкласса при вызове подклассом.Например,

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());
}

Я хотел бы, чтобы это напечатало 6, но вместо этого оно печатает 3.Я хочу сделать это как можно более сухим, поэтому я стараюсь избегать создания второго метода getCost ().Есть какой-либо способ сделать это?Как я могу получить метод суперкласса для использования переменных подкласса при вызове подклассом?То же самое происходит с методами: если у меня есть

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

, на выходе будет «Coffee cost 3», даже когда я вызываю makeCoffee на FancyCoffeeMachine.Почему это?Как я могу это исправить?Или есть лучший способ реализовать эту объектную структуру, которая полностью обходит эту ошибку?

Ответы [ 4 ]

0 голосов
/ 17 февраля 2019

Обычно вы не переопределяете защищенное поле, например cost в подклассе.Вместо этого вы бы дали подклассу способ установить стоимость при создании объекта.Посмотрите на это:

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());
    }
}

(Не беспокойтесь о том факте, что два CoffeeMachine класса объявлены как статические. Просто так они могут быть определены в одном файле.)

Базовый класс CoffeeMachine имеет два конструктора:

  1. Защищенный конструктор, который принимает стоимость в качестве аргумента.
  2. Открытый конструктор, который устанавливает стоимость на 3.

Подкласс FancyCoffeeMachine вызывает защищенный конструктор суперкласса со стоимостью 6. Поэтому переменная cost установлена ​​в 6, и getCost() вернет это значение при запуске:

plain: 3
fancy: 6
0 голосов
/ 17 февраля 2019

Вы вызываете метод getCost из суперкласса (CoffeeMachine), потому что его нет в вашем подклассе (FancyCoffeeMachine).А ваш суперкласс ничего не знает о подклассе и его поле cost.Вам также следует переопределить метод getCost, чтобы он работал так, как вы описали.

0 голосов
/ 17 февраля 2019

Связывание полей не использует динамическую диспетчеризацию, как это делают вызовы виртуальных методов.Ваше поле FancyCoffeeMachine.cost просто скрывает поле CoffeeMachine.cost.

Чтобы достичь того, что вы хотите (например, FancyCoffeeMachine с более высокой стоимостью), вы можете просто установить новое значение на CoffeeMachine.costполе в блоке инициализатора или конструкторе в FancyCoffeeMachine.

public class CoffeeMachine {
    protected int cost = 3;

    protected int getCost() {
        return cost;
    }
}
public class FancyCoffeeMachine extends CoffeeMachine{
    {cost = 6;} // <- sets CoffeeMachine.cost
}
0 голосов
/ 17 февраля 2019

Я почти уверен, что вы также должны переопределить getCost() на FancyCoffeeMachine.

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

    protected int getCost() {
        return cost;
    }
}

Но если бы я хотел реализовать это, я бы сделал CoffeeMachine абстрактным, как этот

abstract class CoffeeMachine {
    private int cost;

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

    int getCost() {
        return cost;
    }
}

, а затем расширите его на моем суперклассе вот так

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

и назовите его таковым

FancyCoffeeMachine fancyCoffeeMachine =  new FancyCoffeeMachine(6);
System.out.println(fancyCoffeeMachine.getCost());
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...