Заставить поле объекта иметь только определенные значения, которые наследуются от родительского класса - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть абстрактный класс Pet с абстрактным методом feed(...). Метод должен принимать только некоторые из трех видов пищи (DRY, WET или RAW). Это может быть тип String, поскольку я использую их только как индикаторы в SWITCH в последующих логах c. Также у меня есть два подкласса Cat и Dog. Они реализуют метод feed(...) от Pet. Наиболее близким, к которому я пришел, является использование ENUM: Pet. java:

public abstract class Pet {

    public enum FoodType {
        DRY,
        WET,
        RAW;
    }

    public abstract void feed(FoodType foodType);
}

Cat. java:

public class Cat extends Pet {

    public void feed(FoodType foodType) {
        switch (foodType) {
            case DRY:
                System.out.println("Feeding this cat dry food.");
                break;
            case RAW:
                System.out.println("Feeding this cat raw food.");
                break;
            case WET:
                System.out.println("Feeding this cat wet food.");
                break;
        }
    }
}

Dog. java:

public class Dog extends Pet {

    public void feed(FoodType foodType) {
        // implementation similar to feed() in Cat.
    }
}

Приложение. java:

import pets.Dog;
import pets.Pet;

public class App {

    public static void main(String[] args) {
        Dog dog01 = new Dog();
        dog01.feed(Pet.FoodType.DRY);
    }
}

Но мне это не нравится, поскольку ENUMS уста- новлены c, по умолчанию к FoodType можно получить доступ из любого места проекта. Не создавая Cat или Dog объект, я могу вызвать Pet.FoodType.DRY из любого места. Предпочтительно он должен быть связан только с объектом, который наследуется от Pet, например:

Dog dog01 = new Dog();
dog01.FoodType.DRY; // do smth with this

Ответы [ 2 ]

1 голос
/ 03 апреля 2020

Это происходит потому, что вы объявили FoodType как publi c. Пожалуйста, замените это на защищенный, и эта проблема будет решена.

protected enum FoodType

В качестве альтернативы, чтобы решить эту проблему, возможно, мы сможем реализовать это как бизнес-логи c

public abstract class Pet {

    protected String[] foodType = new String[]{"RAW","DRY","WET"};

    protected final String RAW_FOOD_TYPE = "RAW";
    protected final String DRY_FOOD_TYPE = "DRY";
    protected final String WET_FOOD_TYPE = "WET";

    public abstract void feed(String foodType);

    public String getRawFoodType()
    {
        return RAW_FOOD_TYPE;
    }

    public String getDryFoodType()
    {
        return DRY_FOOD_TYPE;
    }

    public String getWetFoodType()
    {
        return WET_FOOD_TYPE;
    }

}


public class Cat extends Pet {

    public void feed(String foodType) 
    {
        if(foodType.equals(DRY_FOOD_TYPE))
        {
            System.out.println("Feeding this cat dry food.");
        }
        else if(foodType.equals(RAW_FOOD_TYPE))
        {
            System.out.println("Feeding this cat raw food.");
        }
        else if(foodType.equals(WET_FOOD_TYPE))
        {
            System.out.println("Feeding this cat wet food.");
        }
        else
        {
            throw new RuntimeException("Invalid foodtype");
        }

    }
}


public class App {

    public static void main(String[] args) {
        Cat cat01 = new Cat();
        cat01.feed(cat01.getDryFoodType());

    }
}

```
0 голосов
/ 03 апреля 2020

Так что обычно для этого должно быть хорошо иметь перечисление publi c. Но чтобы ответить на ваш вопрос, да, это возможно, немного изменив структуру. Таким образом, константы здесь могут быть как enum, так и private final string, и все будет в порядке.

Принимая этот случай для enum, объявите его защищенным. Затем создайте метод, который будет возвращать значение enum внутри самого класса Pet, который, по сути, заключает его в геттер.

    public FoodType getFoodType(String foodTypeStr){
        return FoodType.valueOf(foodTypeStr);
    }

Это обеспечит возможность вызова только переменных экземпляра дочерних классов. Следовательно, вы можете сделать что-то вроде этого,

dog01.feed(dog01.getFoodType("DRY"));

Это можно сделать защищенным и овверидировать в ребенка при необходимости.

...