Java расширение / абстракция / вопрос реализации - PullRequest
0 голосов
/ 05 августа 2009

У меня есть три класса (класс A, класс B и класс C).

Класс A вызывает экземпляр B и запускает start ().

Класс B расширяет Thread, поэтому, когда вызывается start (), выполняется что-либо из метода run ().

В потоке run () есть экземпляр класса C.

Есть ли способ разрешить методу в классе C вызывать метод в классе A без создания экземпляра нового класса A?

Поскольку я не могу расширить класс A до класса B (поскольку "Thread" уже расширен), я не знаю, как мне поступить в этом направлении.

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

Спасибо!

Ответы [ 4 ]

1 голос
/ 05 августа 2009

Итак, у вас есть

class A {
 void run()
 {
  new B().start();
 }
}

class B extends Thread {
  public void run(){
    C c = new C();  
    c.do something with 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() ... 
 }
}
1 голос
/ 05 августа 2009

это круговая зависимость, по моему (скромному) мнению, очень плохая вещь в ООП.

Вы должны провести рефакторинг своего кода, чтобы обеспечить общий класс для A и C.

1 голос
/ 05 августа 2009

Наилучшим способом может быть перегрузка начала класса B для получения параметра (A, или, что еще лучше, интерфейса, реализованного A). Затем B может сохранить его для извлечения из C (если это внутренний класс) или передать его конструктору C ...

EDIT:

Хотя, как упомянул комментатор, переопределение конструктора будет работать, оно не соответствует параметрам вопроса, который был сформулирован таким образом, что B уже существует, поэтому я предлагаю перегрузить start () следующим образом:

b.start(A aParam) {
    a=aParam;
    start();
}

Однако эта версия НЕ является поточно-ориентированной. Конструктор B работает, если B действительно создается каждый раз, или если C запускается при запуске b, тогда его можно передать конструктору C по мере его создания.

Кстати, расширение потока обычно не так хорошо, как реализация runnable по целому ряду причин.

0 голосов
/ 05 августа 2009

Еще один способ использовать поведение потоков в Java - реализовать Runnable. Возможно, вы могли бы расширить A, реализовать Runnable и использовать:

Thread t = new Thread( b )
t.start();

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

...