我正在用Java构建一个“联系人管理器”。
我有一个名为“的超类”联系 它有两个基类; 个人联系 和 BusinessContact。
我有一个名为的界面 事件,由类实现 生日 和 会议。 (生日包含一个DateTime对象,而会议有两个开始和结束时间)。
个人联系 拥有一个TreeSet 生日 和 BusinessContact 拥有一套 会议。
现在,在超类中 联系,我想创建一个名为“getEventsWithinPeriod()”的抽象方法,它将在给定的时间跨度内返回所有生日和/或会议的TreeSet。
问题是,我不知道如何告诉抽象方法,然后基类方法返回什么。
例如,这是我使用的代码 联系;
public abstract Set<Event> getEventsWithinPeriod(DateTime start, DateTime end);
在PersonalContact中;
public Set<Birthday> getEventsWithinPeriod(DateTime start, DateTime end){
Set<Birthday> birthdaysThatAreWithin = new TreeSet<Birthday>();
//CODE
return birthdaysThatAreWithin;
但是,在编译器中,我收到了错误 Set<Birthday>
他说;
“返回类型与Contact.getEventsWithinPeriod(DateTime,DateTime)不兼容”
我应该使用的正确条款和回报是什么?为什么我目前的尝试错了?
你有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。
你需要使用 generic Types
public abstract class Contact<T extends Event> {
public abstract Set<T> getEventsWithinPeriod(Date start, Date end);
}
public class BirthDay extends Contact<BirthDay> implements Event {
@Override
public Set<BirthDay> getEventsWithinPeriod(Date start, Date end) {
return null;
}
}
在覆盖任何方法时,方法签名应保持相同,您的签名应保持相同并在PersonalContact类中返回Set
使用泛型时,您不希望显式指定类型。您可以绑定类型,但您不希望显式。
改变你的 Contact
方法
public abstract Set<T extends Event> getEventsWithinPeriod(DateTime start, DateTime end);
并改变 PersonalContact
至
public Set<T extends Event> getEventsWithinPeriod(DateTime start, DateTime end){
Set<T> birthdaysThatAreWithin = new TreeSet<Birthday>();
//CODE
return birthdaysThatAreWithin;
}
那应该得到你想要的东西。