Создание экземпляра переменной в дочернем классе

#java #instantiation

#java #создание экземпляра

Вопрос:

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

 public class Animal{ Food foodType;}
public class Dog extends Animal{ 
   public Dog(){
       foodType=new Food();
   }
}
  

Комментарии:

1. Это возможно, если переменная видна дочернему классу.

2. @nickb Ее экземпляр еще не создан.

3. @Alexis — Я не уверен, что вы получите окончательный ответ на вопрос «почему» кто-то создал экземпляр переменной в дочернем классе, который определен в родительском. Для этого есть множество различных причин, в конечном счете это зависит от дизайна классов и требований к их функциональности.

4. @Alexis Пожалуйста, отредактируйте свой вопрос, похоже, Dog ничего не расширяет.

5. Возможно, это общее поле для двух дочерних элементов и оно будет создаваться по-разному, как food = new Bread (); и food = new Meat ();

Ответ №1:

В этом есть много преимуществ. На самом деле зависит от вашего дизайна.

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

В этом примере мы используем Strategy шаблон проектирования и Inversion of Control . Вы можете видеть, что Animal ничего не знает о реализации Food? Подумайте об этом, Animal.eat() вы можете запускать несколько реализаций без изменения eat() метода. Это немного то, что может сделать ООП.

 public class Main {
    public static void main(String ... args){
        Animal paul = new Dog("Paul");
        Animal elsa = new Cat("Elsa");

        paul.eat();
        elsa.eat();
    }

    public static abstract class Animal {
        private String name;
        protected Food foodType;

        public Animal(String name){
            this.name = name;
        }

        public void eat() {
            System.out.println("The "   name   " has eaten "   foodType.getAmount()   " "   foodType.foodName());
        }
    }

    public static class Dog extends Animal {
        public Dog(String name) {
            super(name);
            foodType = new DogFood();
        }
    }

    public static class Cat extends Animal {
        public Cat(String name) {
            super(name);
            foodType = new CatFood();
        }
    }

    public interface Food {
        int getAmount();
        String foodName();
    }

    public static class DogFood implements Food{
        @Override
        public int getAmount() {
            return 2;
        }

        @Override
        public String foodName() {
            return "beef";
        }
    }

    public static class CatFood implements Food{
        @Override
        public int getAmount() {
            return 5;
        }

        @Override
        public String foodName() {
            return "fish";
        }
    }
}
  

Комментарии:

1. Спасибо за пример. Инверсия управления — это марсианское выражение для меня 🙂

2. Inversion of Control это просто для понимания. Как правило, если объект может выполнять другую реализацию без изменения своего класса, этот класс реализует IoC . Примером является Thread.class , который он использует IoC для обработки выполнения Runnable реализации, ничего не зная об этой реализации.

3. Спасибо, довольно просто, да… Более личный вопрос: сколько времени требуется, чтобы понять шаблоны проектирования и правильно их использовать? Просто подсказка…

Ответ №2:

преимущество:

Например
Если существует класс DogFood, расширяющий Food , Dog может создать его экземпляр (если Dog знает о DogFood), и Animal не обязательно знать о DogFood.

Это упрощает коды.

Ответ №3:

Поскольку food type является свойством Animal и всегда одинаковым для определенного дочернего класса, создайте его final в Animal и передайте через конструктор Animal .

 public class Animal {
    public final Food foodType;

    public Animal(Food foodType) {
        this.foodType = foodType;
    }
}

public class Dog extends Animal{ 
    public Dog() {
       super(new DogFood());
    }
}
  

Теперь у каждого животного (дочернего) есть FoodType, и не нужно заполнять поле родительского класса. Обязанности находятся там, где они должны быть.