Javaの:親にキャストせずに子供を受け入れるようにする方法を書くためにどのように?
-
20-09-2019 - |
質問
わからないどのようにタイトルこの...
Event
、WeightEvent
、TimedEvent
:だから私はRepEvent
の3つのクラスを持っています。どんな手段を通じ、私は子供の1のオブジェクトを取得します。今、私はそれがgetSavedEvents()
方法でそれからデータを引き出すことができるように、別のオブジェクトのメソッドにその子のイベントを送信します。データを引っ張っするイベントのタイプに固有であるため、この方法は、子供だけに存在します。
私は
で開始しましたpublic void setEvent(Event e) {
それはEvent
(親)オブジェクトに私の子オブジェクトをキャスト。
3つの異なる方法を書いているこの短い周りにどのような方法があります。子供のための一つの各?
public void setEvent(WeightEvent e) { public void setEvent(TimedEvent e) { public void setEvent(RepEvent e) {
何かアドバイスをありがとう。
- ジョン
解決
の代わりにタイプに切り替えるのあなたは、イベントタイプのタイプごとに異なる定義のイベントのメソッドを呼び出す必要があります。これは Template Methodパターンに呼ばれています。
(これはところで、C ++のテンプレートとは何の関係もありません)このパターンを使用して、あなたのイベント表のクラスは、このようなものになります:
public class EventTable {
public void setEvent(Event e) {
int x = 0;
columns = e.getFields();
Event[] savedEvents = e.getSavedEvents();
for(Event ev : savedEvents) {
tempdata[x] = ev.getTempData();
x++;
}
}
}
全体スイッチgetTempData()への単一の呼び出しに置き換えられていることに留意されたいです。この方法は、ちょうどgetSavedEventsのように、イベントに続い抽象的です。
public abstract class Event {
public Date getDate() { return(_date); }
public abstract Event[] getSavedEvents();
public abstract int[] getTempData();
public int[] getFormattedDate() {
...
}
次に、各サブクラスでgetTempData()メソッドを定義します。たとえばます:
public class WeightEvent extends Event {
public int getWeight() { return(_weight); }
public int getReps() { return(_reps); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getWeight(),
getReps()
};
}
}
public class TimedEvent extends Event {
public String getTimeInHMS() { return(_timeString); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getTimeInHMS()
};
}
}
public class RepEvent extends Event {
public int getReps() { return(_reps); }
public int[] getTempData() {
return new int[]{
getFormattedDate()[0],
getReps()
};
}
}
他のヒント
参照がキャストされていても、それが実際のオブジェクトの種類を変更しません。あなたは上の参照を渡すと、それはまだ子オブジェクトのインスタンスへの参照になります。必要であれば、通常、これは親タイプで適切な抽象メソッドで、十分だろう。
あなたが望む方法は子供のタイプに固有のものであり、あなたがそれらのすべてを包括的に実装することができ、適切な抽象化を思い付くことができない場合は、しかし、あなたはあなたのinstanceof
コード内setEvent
を使用するために持っているのいずれかまたはあなたがをはイベントの正確な種類に応じて、コードの異なるビットをコールする必要があるとしているので...あなたの方法をオーバーロードする必要があります。
私たちは、メソッドのシグネチャのカップルを除いて、あなたのコードのいずれかを見ることができないので、これはすべてのビット曖昧です。あなたは、特にsetEvent
は、子クラスの異なるメソッドが何であるかを達成し、する必要があるものの面で、何をしようとしてについてGoogleに詳細を与えることができれば、我々はより多くのを助けることができるかもしれません。
これを行うには、ジェネリックを使用することができます。
次のようにイベントクラスを定義します:
public abstract class Event<T extends Event> {
public abstract void setEvent(T e);
}
このイベントを拡張する任意のタイプを使用して作成されることを期待クラスを定義します。
次に、あなたの子クラスであなたがジェネリック型として子クラスを使用して、このような何かを実装します:
class WeightEvent extends Event<WeightEvent>
{
@Override
public void setEvent(WeightEvent e) {
...
}
}
私はgetSavedEvents()
変数を持つとき、あなたのprobemがEvent
を呼び出していると思います。
もしそうなら、また抽象宣言されなければならないgetSavedEvents()
する抽象Event
方法を、追加します:
public abstract class Event {
public abstract Events getSavedEvents();
...
}
Event
is抽象ので、あなたはそれのインスタンスを作成することはできません。使用されるようにサブクラス化する必要があります。それが問題である場合は、Event.getSavedEvents()
に(すべてでは何も、単にヌルを返さない)例外をスローしたり、アプリケーションのための合理的な何かを実行します。
public class Event {
public Events getSavedEvents() {
throw new UnsupportedOperationException("must be called in a child class");
// OR return null;
...
}
今あなたが他のオブジェクトにgetSavedEvents()
メソッドを呼び出すことができます:
public class OtherObject {
private Event event;
public void setEvent(Event e) {
event = e;
...
Events events = event.getSavesEvents();
e
の実際のクラスによって実装される方法は、例えば、使用されますe
がTimedEvent
であれば、そのクラスのメソッドが呼び出されます。
あなたでしインタフェースの背後に抽象化問題外。
interface IEvent
{
abstract public void doSomething();
}
すると例えば、すべてのイベントクラスがそれを実装しています。
class WeightedEvent implements IEvent
{
public void doSomething()
{
// do something
}
}
次に、あなたは、単一のメソッドを必要とし、任意の型チェックを行う必要はありません。
public void setEvent(IEvent e)
{
e.doSomething();
}
HTH
あなたは Visitorパターンを使用することができますように。
すべての子がそのメソッドを実装しているので、抽象getSavedEventsを手伝ってくれました()メソッドを使用します。
ここでsetEvent()のためのコードです
public class EventTable {
public void setEvent(Event e) {
int x = 0;
int type = e.getEventType();
columns = e.getFields();
Event[] savedEvents = e.getSavedEvents();
for(Event ev : savedEvents) {
tempdata[x][0] = ev.getFormattedDate()[0];
switch(type) {
case EVENTTYPE.WEIGHT:
tempdata[x][1] = ev.getWeight();
tempdata[x][2] = ev.getReps();
break;
case EVENTTYPE.TIMED:
tempdata[x][1] = ev.getTimeInHMS();
break;
case EVENTTYPE.REP:
tempdata[x][1] = ev.getReps();
break;
}
x++;
}
}
}
このコードでは)私はイベントクラスを「抽象」を追加し、getSavedEvents(という抽象メソッドを定義した後で動作します。
次の問題がgetWeight()、getReps()とgetTimeInHMS()メソッドです。彼らは、子イベントのタイプに固有のものであり、再度、親イベントクラスには存在しません。私はイベントでそれらを抽象的にする場合は、今私はgetRepsは()TimedEventのためのコンテキストを持っていないにも関わらず、それぞれの子でそれらを定義する必要があります。
public class Event {
public Date getDate() { return(_date); }
}
public class WeightEvent extends Event {
public int getWeight() { return(_weight); }
public int getReps() { return(_reps); }
}
public class TimedEvent extends Event {
public String getTimeInHMS() { return(_timeString); }
}
public class RepEvent extends Event {
public int getReps() { return(_reps); }
}
当然、コードの略称。 WeightEventsは、日付、重量とそれらに関連付けられている担当者を持っています。 TimedEventsは、それらに関連した時間の日付と長さを持っています。 RepEventsは、それらに関連する担当者の日付と番号を持っています。彼らはイベント全体に共通しているので、最新の方法は、すべての親です。
私は抽象)getWeight()、getRepsを(作り、彼らだけが関連している子でそれらを宣言していない場合は、、ここで私は上記のコピーsetEvent()メソッドでイベント表から取得エラーです。
EventTable.java:124: cannot find symbol
symbol : method getWeight()
location: class Event
tempdata[x][1] = ev.getWeight();
- ジョン
あなたは子クラスにEvent e
オブジェクトをキャストすることができ - 私はJavaでinstanceof
演算子は、お手伝いをすると思います。