2016-07-27 3 views
1

Так что проблема, с которой я сталкиваюсь, - это. Я написал метод как часть программы, которую я использую для отображения всех объектов в ArrayList. В этом ArrayList хранятся три разных типа объектов: грибы, цветы и сорняки. Я могу позвонить plantList.get(i).getName() и plantList.get(i).getColor методам без проблем. Обе эти переменные относятся к родительскому классу Plant. Однако при вызове следующего метода plantList.get(i).getPoison() (этот метод относится к подклассу Fungus) Я получаю ошибку компилятора, говоря, что он не может найти переменную Fungus.Доступ только к переменным класса родителя из метода

Я пробовал это с любой другой переменной, уникальной для подкласса, и происходит то же самое. Поэтому я могу получить доступ к переменным из родительского класса «Завод», но не из каких-либо подклассов «Fungus» «Flower» или «Weed». Я новичок в использовании подклассов и суперклассов, поэтому мне сложно определить, где именно возникает проблема.

public static void displayPlant(ArrayList<Plant> plantList) { 
    for (int i = 0; i < plantList.size(); i++) { 
     System.out.print(plantList.get(i).getName()); 
     System.out.print(plantList.get(i).getID()); 
     System.out.print(plantList.get(i).getColor()); 
     if (plantList.get(i).contains(Fungus) == true) { 
      System.out.print(plantList.get(i).getPoison()); 
     } 
     else if (plantList.get(i).contains(Flower) == true) { 
      System.out.print(plantList.get(i).getSmell()); 
      System.out.print(plantList.get(i).getThorns()); 
     } 
     else { 
      System.out.print(plantList.get(i).getPoison()); 
      System.out.print(plantList.get(i).getEdible()); 
      System.out.print(plantList.get(i).getMedicinal()); 
     } 
    } 
} 
+0

Ожидаемое поведение. Вы должны набирать приведение к соответствующему типу дочернего класса, чтобы получить доступ к методам, специфичным для дочернего класса. – JavaHopper

ответ

0

Java является strongly typed Язык. Это означает, что если вы хотите использовать методы дочернего класса, вы должны указать cast down на класс child.

В вашем примере:

... 
else if (plantList.get(i) instanceof Fungus) { //check if plant is fungus 
    System.out.print(plantList.get(i).getSmell()); 
    System.out.print(((Fungus)plantList.get(i)).getThorns()); //downcasting 
} 
... 

Ваш чек с помощью constains не будет работать. Чтобы проверить тип объекта, вам необходимо использовать оператор instanceof.

+1

Большое вам спасибо! Это решает другую сторону моей проблемы, которая выполняет команды дочерних классов. Большое спасибо –

+0

Пожалуйста, поддержите anwsers, которые вам нравятся, и, возможно, отметьте один как правильный anwser. –

2

Хорошее решение - использовать динамическую отправку. То есть пусть сам элемент решает, какую информацию он хочет распечатать.

class Plant { 
    ... 
    public String toString() { 
     return String.join(" ", getName(), getID(), getColor()); 
    } 
} 

class Fungus extends Plant { 
    ... 
    @Override 
    public String toString() { 
     return String.join(" ", super.toString(), getPoison()); 
    } 
} 

class Flower extends Plant { 
    ... 
    @Override 
    public String toString() { 
     return String.join(" ", super.toString(), getSmell(), getThorns()); 
    } 
} 

class Weed extends Plant { 
    ... 
    @Override 
    public String toString() { 
     return String.join(" ", super.toString(), getPoison(), getEdible(), getMedicinal()); 
    } 
} 

Ваш цикл будет выглядеть следующим образом:

public static void displayPlant(ArrayList<Plant> plantList) { 
    for(Plant p : plantList) 
     System.out.println(p); // This calls toString 
} 
+0

PS. В 'toString' я использовал' String.join' для создания строки типа 'value1 value2 value3'. Но, конечно, вы можете вернуть 'String' в любом формате, который вам нужен. –

+0

Спасибо за помощь! Мне нужно немного подождать, чтобы посмотреть на это решение и переварить его, но это кажется намного более кратким, чем то, как я это делал. –

1

На самом деле вы делаете это в неправильном направлении,

После того, как вы держите объект дочернего класса в переменной класса родителя, то при компиляции время поиска или поиска только тех методов и переменных, которые объявлены в родительском классе.

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

public static void displayPlant(ArrayList<Plant> plantList) { 
    for (int i = 0; i < plantList.size(); i++) { 
     Plant plant=plantList.get(i); 
     if (plant instanceof Flowers) { 
      Flowers fl=(Flowers)plant; 
      //TODO do whatever you want to do 
     } 
     else if(plant instanceof Weeds) { 
      Weeds wd=(Weeds)plant; 
      //TODO do whatever you want to do 
     }else if (plant instanceof Fungus) { 
      Fungus wd=(Fungus)plant; 
      //TODO do whatever you want to do 
     } 
    } 

Я надеюсь, что это поможет вам. Спасибо

+1

Большое спасибо! Я думаю, что это то, что я ищу с точки зрения структуры. Я воспользуюсь этим позже сегодня/завтра и сообщаю о том, как это работает. –