1

不知道如何命名这个...

所以我有三个子类EventWeightEvent, TimedEvent, RepEvent。通过任何方式,我得到了其中一个孩子的物品。现在我想将该子事件发送到另一个对象中的方法,以便它可以使用该getSavedEvents()方法从中提取数据。该方法仅存在于子项中,因为拉取数据是特定于事件类型的。

我从

公共无效setEvent(事件e){

但这会将我的子对象转换为Event(父)对象。

有什么办法可以绕过这三种不同的方法。给孩子一个?

公共无效 setEvent(重量事件 e){
公共无效setEvent(TimedEvent e){
公共无效setEvent(RepEvent e){

感谢您的任何建议。

-约翰

4

8 回答 8

7

即使引用被强制转换,它也不会改变实际对象的类型。当您传递引用时,它仍然是对子对象实例的引用。通常这已经足够了,如果需要的话,在父类型中使用适当的抽象方法。

但是,如果您想要的方法特定于子项的类型,并且您无法提出所有这些方法都可以通用实现的适当抽象,那么您要么必须在代码中使用instanceof要么setEvent必须使用重载您的方法...因为您将不得不根据事件的确切类型调用不同的代码位。

这有点模糊,因为除了几个方法签名之外,我们看不到您的任何代码。如果您可以向我们提供有关您正在尝试做的事情的更多详细信息,特别是在setEvent需要实现的目标以及子类中的不同方法方面,我们可能会提供更多帮助。

于 2009-12-17T07:24:42.863 回答
3

而不是打开类型,您应该在事件上调用一个方法,该方法为每种类型的事件类型定义不同。这称为模板方法模式。(它与 C++ 模板无关,顺便说一句)

使用此模式,您的 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()
    };
  }
}
于 2009-12-19T05:01:01.780 回答
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) {
        ...
    }

}
于 2009-12-17T08:03:14.763 回答
1

getSavedEvents()我认为您的探针在有Event变量时正在调用。
如果是这样,向 中添加一个抽象getSavedEvents()方法Event,该方法也必须声明为 abstract :

    public abstract class Event {
        public abstract Events getSavedEvents();
        ...
    }

因为Event是抽象的,你不能创建它的实例;它必须被子类化才能使用。如果这是一个问题,请在以下位置抛出异常或为您的应用程序做任何合理的事情(什么都不做,只返回 null)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是 a TimedEvent,则将调用该类中的方法。

于 2009-12-17T10:41:20.423 回答
0

您可以将Event e对象强制转换为子类——我认为instanceofJava 中的运算符会对您有所帮助。

于 2009-12-17T07:25:42.520 回答
0

您可以在接口后面抽象出问题

interface IEvent
{
    abstract public void doSomething();
}

然后让你所有的事件类实现它,例如

class WeightedEvent implements IEvent
{
    public void doSomething()
    {
        // do something
    }
}

然后你只需要一个方法,不需要做任何类型检查

public void setEvent(IEvent e)
{
    e.doSomething();
}

高温高压

于 2009-12-17T07:54:05.360 回答
0

可能您可以使用访问者模式

于 2009-12-17T13:30:22.337 回答
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++;
 }
}
}

在我将“抽象”添加到 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();

-约翰

于 2009-12-17T18:10:52.720 回答