您有 3 个解决方案。
解决方案 1
首先,您可以使您的类通用,如下所示:
public abstract class Contact<E extends Event> {
// ...
public abstract Set<E> getEventsWithinPeriod(DateTime start, DateTime end);
}
然后在你的具体实现中:
public class PersonalContact extends Contact<Birthday> {
public Set<Birthday> getEventsWithinPeriod(DateTime start, DateTime end) { ... }
}
这是最好的解决方案,但您有一些选择。
解决方案 2
您可以更改birthdaysThatAreWithin
字段的类型:
Set<Event> birthdaysThatAreWithin = new TreeSet<Event>();
以及更改方法签名:
public Set<Event> getEventsWithinPeriod(DateTime start, DateTime end) {
并像这样返回它。这会限制您,因为您不能再将事件用作Birthday
实例。
解决方案 3
您还可以将您的方法签名(在您的抽象类和具体类中)更改为:
public Set<? extends Event> getEventsWithinPeriod(DateTime start, DateTime end)
而不是改变任何其他东西。这与解决方案 2 具有相同的问题,如果不强制转换它们,您将无法将事件用作Birthday
实例。
编辑: 2 和 3 的缺点是它们需要铸造。例如:
PersonalContact contact = ... ;
Set<Event> events = personalContact.getEventsWithinPeriod(start, end);
// I know all the events are birthdays, but I still have to do this:
for (Event event : events) {
if (event instanceof Birthday) {
Birthday birthday = (Birthday) event;
// Do stuff with birthday
} // else maybe log some error or something
}
使用第一个解决方案,您将拥有:
PersonalContact contact = ... ;
Set<Birthday> birthdays = personalContact.getEventsWithinPeriod(start, end);
for (Birthday birthday : birthdays) {
// Do stuff with birthday
}
代码看起来更干净并且运行得更好,因为您不必进行instanceof
检查以确保您没有获得ClassCastException
. 你也可以有这样的东西:
public static void processBirthdaysFor(Contact<Birthday> birthdayContact, DateTime start, DateTime end) {
Set<Birthday> birthdays = personalContact.getEventsWithinPeriod(start, end);
for (Birthday birthday : birthdays) {
// Do stuff with birthday
}
}
而且,如果您有另一个Contact
具有Birthday
事件的实现,则可以将它们传递给该processBirthdaysFor
方法而无需进行任何更改。
但是,如果您只需要事件而不关心调用您的代码中的类型是什么Contact.getEventsWithinPeriod
,那么解决方案 2 和 3绝对是您最好的选择。如果是这种情况,我个人会使用解决方案 2。