不确定如何标题...
所以我有三个Event
子类:WeightEvent
,TimedEvent
,RepEvent
。通过任何方式,我得到一个孩子的对象。现在我想将该子事件发送到另一个对象中的方法,以便它可以使用getSavedEvents()
方法从中提取数据。该方法仅存在于子项中,因为提取数据特定于事件类型。
我从
开始public void setEvent(Event e) {
但是将我的子对象强制转换为Event
(父)对象。
有没有办法解决这三种不同方法的问题。一个孩子一个人?
public void setEvent(WeightEvent e) { public void setEvent(TimedEvent e) { public void setEvent(RepEvent e) {
感谢您的任何建议。
-John
答案 0 :(得分:7)
即使引用是强制转换的,它也不会更改实际对象的类型。当您传递引用时,它仍将是对子对象的实例的引用。通常这是足够的,如果需要,在父类型中使用适当的抽象方法。
但是,如果您想要的方法特定于子类型,并且您无法提出适当的抽象,而且所有这些抽象都可以通用,那么您必须使用instanceof
在您的setEvent
代码中或做必须重载您的方法...因为您将不得不根据事件的确切类型调用不同的代码位。
这有点模糊,因为除了几个方法签名之外我们看不到任何代码。如果您可以向我们提供有关您正在尝试做什么的更多详细信息,特别是在setEvent
需要实现的内容以及子类中的不同方法方面,我们可以提供更多帮助。
答案 1 :(得分:3)
不应该打开类型,而应该为每种类型的事件类型定义不同的事件调用方法。这称为Template method pattern。 (它与C ++模板无关,BTW)
使用此模式,您的EventTable类将变为如下所示:
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()的单次调用。这个方法在Event中是抽象的,就像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()
};
}
}
答案 2 :(得分:1)
您可以使用泛型来执行此操作。
按如下方式定义Event类:
public abstract class Event<T extends Event> {
public abstract void setEvent(T e);
}
这定义了一个期望用任何扩展Event的类型创建的类。
然后在您的子类中使用子类作为泛型类型实现类似的东西:
class WeightEvent extends Event<WeightEvent>
{
@Override
public void setEvent(WeightEvent e) {
...
}
}
答案 3 :(得分:1)
我认为你的probem在拥有getSavedEvents()
变量时正在调用Event
如果是这样,请向getSavedEvents()
添加一个抽象的Event
方法,该方法也必须声明为abstract:
public abstract class Event {
public abstract Events getSavedEvents();
...
}
因为Event
是抽象的,所以你无法创建它的实例;它必须是子类才能使用。如果这是一个问题,请在Event.getSavedEvents()
中抛出一个Exception或对你的应用程序做任何合理的事情(一无所有,只返回null):
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
,则会调用该类中的方法。
答案 4 :(得分:0)
您可以将Event e
对象强制转换为子类 - 我认为Java中的instanceof
运算符可以帮助您。
答案 5 :(得分:0)
您可以在界面后面抽象问题
interface IEvent
{
abstract public void doSomething();
}
然后让你所有的事件类都实现它,例如
class WeightedEvent implements IEvent
{
public void doSomething()
{
// do something
}
}
然后您只需要一个方法,不需要进行任何类型检查
public void setEvent(IEvent e)
{
e.doSomething();
}
HTH
答案 6 :(得分:0)
可以使用Visitor pattern。
答案 7 :(得分:0)
使用abstract帮助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++;
}
}
}
在我将“abstract”添加到Event类并定义了一个名为getSavedEvents()的抽象方法之后,此代码可以正常工作。
下一个问题是getWeight(),getReps()和getTimeInHMS()方法。它们特定于子事件的类型,并且在父事件类中也不存在。如果我在Event中将它们变为抽象,那么现在我必须在每个子节点中定义它们,即使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得到的错误:
EventTable.java:124: cannot find symbol
symbol : method getWeight()
location: class Event
tempdata[x][1] = ev.getWeight();
-John