#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, и не нужно заполнять поле родительского класса. Обязанности находятся там, где они должны быть.