ArrayList и его тип при наследовании

294
10 мая 2021, 00:10

Задание: Написать программу которая будет иметь классы и они будут наследоваться. Animal -> Felling -> Tiger, Lion, Cat.

Вопрос: В своём коде я создавал каждый конечный элемент иерархии наследования (Tiger, Lion, Cat) по одному экземпляру и добавлял их в ArrayList

    ArrayList<Animals> animals = new ArrayList<>();
        animals.add(new Cat());
        animals.add(new Tiger());
        animals.add(new Lion());

Вот методы классов

abstract public class Animals {
    abstract public void voice();
    abstract public void walk();
    abstract public void eat();
abstract public class Felline extends Animals {
    abstract public void voice();
    public void walk(){
        System.out.println("Walking like a Felline");
    }
    public void eat(){
        System.out.println("Eating like a Felline");
    }
    public void sitDown(){
        System.out.println("Sitting down like a Felline");
    }
}
public class Cat extends Felline{
    @Override
    public void voice(){
        System.out.println("Mew!");
    }
}

(В классах Tiger, Lion тоже самое что и в Cat)

Я могу получить доступ к методам класса Animal таким образом

animals.get(i).voice();

Но каким образом теперь мне можно получить метод sitDown()?

Буду очень признателен за ответ. 3 день не могу найти решение.

Answer 1

В данном примере используется 2 уровня абстракции, классы: Animals (первый (высший) уровень) и его наследник Felline (второй уровень). В классе Felline добавлен новый метод public void sitDown();, который "не виден" в супер-классе Animals. Он об этом методе даже "не догадывается"))) Далее - при создании коллекции ArrayList ты указал, что в ней будут храниться объекты типа Animals

ArrayList<Animals> animals = new ArrayList<>();

т.е. классы, наследуемые от высшей ступени твоей иерархии абстракции (Animals - Felline - Cat,Dog,Lion), что вполне допустимо. При использовании метода voice(); любого элемента коллекции проблем нет. Этот метод "известен" на всех уровнях абстракции. А вот с методом sitDown(); немного сложнее. Ты указал, что тип элементов коллекции будет Animals, но на этом (высшем) уровне этот метод не виден(см.выше).

Таким образом, чтобы использовать данный метод необходимо либо явно, прямо в коде приводить к типу Felline:

((Felline)animals.get(i)).sitDown()

о чём тебе пояснил Serodv, либо поменять тип элементов при объявлении коллекции, понизить его до уровня Felline:

import java.util.ArrayList;
public class AnimalTestDrive{
    public static void main(String[] args){
        ArrayList<Felline> animals = new ArrayList<>();
        animals.add(new Cat());
        animals.get(0).voice();
        animals.get(0).sitDown();       
    }
}

Кстати, на заметку, английское слово Feline (кошачий) пишется с одной буквой "l", но это я так, для расширения кругозора )))

Answer 2

Ваш ArrayList может хранить либо объекты типа Animals, либо экземпляры его подклассов. Но в классе Animals отсутствует метод sitDown(), а значит, не все Animals могут обладать данным методом (а только лишь Feline, где вы его определили).

Следовательно, есть 2 выхода из данной ситуации:

  1. Исходя из вашего кода, ваш ArrayList хранит лишь только экземпляры подклассов класса Feline (Cat, Lion, Tiger), а значит, изменив тип Animals на Feline, вы буквально скажите, что мой ArrayList будет состоять только из Feline и экземпляров его подклассов. Но, как было сказано выше, ваш метод sitDown() находится в абстрактном классе Feline, а значит, все его подклассы тоже имеют данный метод. Таким образом, можно просто вызвать данный метод:

    List<Feline> felines = new ArrayList<>();
    felines.sitDown();
    
  2. Если же в вашем ArrayList могут быть и другие Animals (не Feline), то у них этот метод отсутствует, следовательно, нужно делать проверку instanceof, а также приведение типов, что накладывает дополнительные расходы и ухудшает читаемость кода.

Замечания:

  • Используйте единственное число в названиях классов (если этот класс не является util-классом, такие как Arrays и т.д.);
  • Программируйте к интерфейсу, а не к конкретной реализации (принцип подстановки Барбары Лисков):

    List<Animals> animals = new ArrayList<>()
    
READ ALSO
Ошибка, Не может найти главный класс

Ошибка, Не может найти главный класс

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

229
Плагин начинает работать, но почему выполняется только одно действие? [закрыт]

Плагин начинает работать, но почему выполняется только одно действие? [закрыт]

Хотите улучшить этот вопрос? Добавьте больше подробностей и уточните проблему, отредактировав это сообщение

98
Доступ к елементам массива, которые являются экземплярами классов, которые связаны между собой

Доступ к елементам массива, которые являются экземплярами классов, которые связаны между собой

Я хочу сделать игру платформер (используя Processing) и столкнулся с такой проблемойУ меня есть 2 типа блоков: стационарные (неподвижные) и те которые...

114
Ошибка в Eclipse Window Builder: This is not a GUI class and can&#39;t be edited graphically?

Ошибка в Eclipse Window Builder: This is not a GUI class and can't be edited graphically?

Появилась ошибка в Eclipse Window Builder Я в eclipse новичок, не знаю как исправить!

343