Задачу решил, но появилась куча вопросов: static { threads.add(new ThreadOne()); threads.add(new ThreadTwo()); threads.add(new ThreadThree()); threads.add(new ThreadFore()); threads.add(new ThreadFive()); } Если в мэйне нужно вызвать метод у объекта ThreadFore почему нельзя написать :
(ThreadFore) threads.get(3).showWarning;
а так можно :
ThreadFore threadFore = (ThreadFore) threads.get(3);
threadFore.showWarning;
И еще вопрос в целом про наследование и реализацию интерфейсов (все никак эта тема меня не отпускает). Поправьте меня если я не прав. Как я понял в этой задаче мы когда создаем статический блок
static {

        threads.add(new ThreadOne());
        threads.add(new ThreadTwo());
        threads.add(new ThreadThree());
        threads.add(new ThreadFore());
        threads.add(new ThreadFive());
    }
и добавляем туда наши объекты которые унаследованы от Thread мы получается сужаем наши объекты до Thread ? И эти суженные объекты ничего не знают о методах изначального класса, таких как :
threads.get(3).showWarning;
зато если мы обратно их расширим они узнают, парвильно ?
ThreadFore threadFore = (ThreadFore) threads.get(3);
threadFore.showWarning;
Значит что, когда мы сужаем что происходит? Создается неявно какой-то временный объект того типа к которому мы хотим сузить ( в данном случае к Thread) с переопределенным методом? А когда мы расширяем обратно, как он узнает обратно о "забытых" методах? Где - то внутри хранит ссылку на старый объект и когда расширился обратно так-же неявно присвоил ее новой копии от изначального объекта? И еще вопрос если бы например было не наследование, а реализация интерфейса Runnable
public static class ThreadFore implements Runnable
я бы все равно не смог вызвать?
threads.get(3).showWarning;
И что конкретно происходит при реализации интерфейса? В класс Thread передается нечто вроде Runnable ThreadFore и это нечто знает только о методе run() но также хранит ссылку на изначальный объект до которого при необходимости это нечто можно расширить?