Помогите, пожалуйста, с созданием экземпляра случайного класса в Java

Есть 4 класса Main, Animal, Dog, Parrot, два последние наследуют класс Animal. Но в классе Parrot есть метод fly(). Суть вопроса, мне нужно создать экземпляр одного из классов Dog, Parrot, следующим образом.

gn = random.nextInt(2);
        if(gn == 0)
        Dog mob = new Dog();
        else
        Parrot mob = new Parrot();

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

Я решил эту проблему иначе

Animal mob;

        gn = random.nextInt(2);
        if(gn == 0)
             mob = new Dog();
        else
             mob = new Parrot();

но проблема в том, что метод fly() будет не доступен если такого метода нет в классе Animal. Можно его туда добавить и он будет замещен нужным методом из класса Parrot. Но если таких классов будет много и у все разные методы, то нужно будет их все добавлять в суперкласс и получится, что там будет огромное скопление методов со всех подклассов. Не будет ли это противоречить принципу наследования в Java. Спасибо.

Какая конечная цель вашего примера? Чего вы в итоге пытаетесь добиться? Как вы можете ожидать конкретный метод fly, работая в условиях неопределенности? Вероятность его появления - 0.5.

Приведение к базовому типу верное, но добавлять туда специфические методы наследников не имеет никакого смысла. Это логически неверно. Либо вызывайте общие для всех классов животных переопределенные методы (по типу eat, sleep), либо не морочьте себе голову с рандомизацией.

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

Как пример приходит на ум рандомизация в игре, когда из одного и того же босса выпадают разные предметы и уже в зависимости от того, что это за предмет, над ним можно производить разные действия, к примеру выпить если это зелье или взять в руку если это оружие. Мне нужна примерно такая же логика. Здесь я привел в пример 2 класса Dog и Parrot, на самом деле их около 50 и рандомизация выглядит более оправданно чем если бы их было 2.

Тыц

1 лайк

С точки зрения “игрока” - действие одно - use(), а “выпить” или “взять” - это детали реализации.

Я так понял, по максимуму задать переменные и методы в суперклассе, а реализацию их уже по принципу полиморфизма в подклассах подкорректировать для нужного персонажа? К примеру переменную int health я не задавал в суперклассе, так как подумал, что у каждого животного будет свое количество жизни. Но это не правильно, так как у всех животных есть эта характеристика, значит и в суперклассе должно быть int health. А в подклассах уже переменная будет переопределена для каждого животного. Или как это можно лучше реализовать, подскажите пожалуйста?

Мне кажется, Вы тут уже ответили на свой вопрос:
Создавать нужно Животное, соответственно в качестве класса-предка, от которого вы наследуете классы, экземпляры которых будете создавать: нужен класс, например: animal
я бы предложил сделать его абстрактным и задать только названия методов и переменных присущих для всех классов наследников:
Условно как-то так:

abstract class Animal {
    int health;

    public void move() { }
}

Потом уже пишите классы ваших “частных” случаев:

class Dog extends Animal {
    int health = 5;
    
    public void move() {
        //реализация метода run
    }
}

class Parrot extends Animal {
    int health = 2;

    public void move() {
        //реализация метода fly
    }
}

а в других местах кода, где Вы заставляете этот объект двигаться: обращаетесь к объекту через класс родитель:

Animal pet1 = new Dog();
Animal pet2 = new Parrot();

pet1.move();
pet2.move();

Дальше возникнет вопрос “А как же частные методы?”:
Перед вызовом частного метода проверяем объект какого класса в нашей переменной, К примеру добавили метод “void a()” в класс parrot и метод “void b()” в класс dog, тогда использование методов может выглядеть как-то так:

animal pet1 = new dog();
animal pet2 = new parrot();

if (pet1 instanceof dog) {
    ((dog)pet1).b();
} 
if (pet2 instanceof parrot) {
    ((parrot)pet2).a();
}
2 лайка

А если ты не знаешь, какие там будут методы, в созданном объекте, то тут уже рефлексией вроде попахивает

Спасибо, хороший вариант, попробую так сделать