Вопрос о расширении Java / абстракции / реализации
-
22-07-2019 - |
Вопрос
У меня есть три класса (класс A, класс B и класс C).
Класс A вызывает экземпляр B и запускает start().
Класс B расширяет поток, поэтому при вызове start() выполняется все, что содержится в методе run().
В потоке run() есть экземпляр класса C.
Можно ли в любом случае разрешить методу в классе C вызывать метод в классе A без создания нового экземпляра класса A?
Поскольку я не могу расширить класс A до класса B (потому что "Поток" уже расширен), я не знаю, как бы я это сделал.
Извините за расплывчатость, но мой проект содержит слишком много кода и слишком сложен, чтобы привести прямой пример кода.
Спасибо!
Решение
Итак, у вас есть
class A {
void run()
{
new B().start();
}
}
class B extends Thread {
public void run(){
C c = new C();
c.do something with A .. }
}
Вы можете передать вызывающего абонента, что может стать некрасивым, так как вам нужно передать A вплоть до C через B:
class A {
void run()
{
new B(this).start();
}
}
class B extends Thread {
public void run(A a){
C c = new C();
c.do something(a)..
}
}
или упростить, особенно если у B и C нет другой причины для:
class A {
public void run()
{
this.do something() ...
}
}
Другие советы
это циклическая зависимость, по моему (скромному) мнению, очень плохая вещь в ООП.
Вы должны провести рефакторинг своего кода, чтобы предоставить общий класс для A и C.
Лучшим способом может быть, чтобы класс B начал перегружаться, чтобы принять параметр (A или, еще лучше, интерфейс, реализованный A).Затем B может либо сохранить это для извлечения C (если это внутренний класс), либо передать его конструктору C...
Редактировать:
Хотя, как упомянул комментатор, переопределение конструктора сработало бы, это не соответствует параметрам вопроса, который был сформулирован таким образом, что B уже существовал, поэтому мое предложение состоит в том, чтобы перегрузить start() следующим образом:
b.start(A aParam) {
a=aParam;
start();
}
Однако эта версия НЕ является потокобезопасной.Конструктор B работает, если экземпляр B фактически создается каждый раз, или если экземпляр C создается при запуске b, тогда он может быть передан конструктору C по мере создания экземпляра.
Кстати, расширение потока, как правило, не так хорошо, как реализация runnable по целому ряду причин.
Другой способ использовать поведение потока в java - это реализовать Runnable.Предположительно, вы могли бы расширить A, и реализовать Runnable, и использовать:
Thread t = new Thread( b )
t.start();
Кажется уродливым с точки зрения ООП, но при определенных обстоятельствах это могло бы иметь смысл.Два других ответа кажутся немного более разумными, но я подумал, что это можно рассмотреть.