Cod*_*ein 11 java generics set
我正在用Java构建一个"联系人管理器".
我有一个名为" Contact的超类,它有两个基类; PersonalContact和BusinessContact.
我有一个名为Event的接口,它由类Birthday和Meeting实现.(生日包含一个DateTime对象,而会议有两个开始和结束时间).
PersonalContact拥有一个生日树组,BusinessContact拥有一组会议.
现在,在超类Contact中,我想创建一个名为"getEventsWithinPeriod()"的抽象方法,它将在给定的时间跨度内返回所有生日和/或会议的TreeSet.
问题是,我不知道如何告诉抽象方法,然后基类方法返回什么.
例如,这是我在Contact中使用的代码;
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;
Run Code Online (Sandbox Code Playgroud)
但是,在编译器中,我说错了Set<Birthday> ;
"返回类型与Contact.getEventsWithinPeriod(DateTime,DateTime)不兼容"
我应该使用的正确条款和回报是什么?为什么我目前的尝试错了?
Ami*_*nde 10
你需要使用 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;
}
}
Run Code Online (Sandbox Code Playgroud)
你有3个解决方案.
解决方案1
首先,您可以使您的类具有通用性,如下所示:
public abstract class Contact<E extends Event> {
// ...
public abstract Set<E> getEventsWithinPeriod(DateTime start, DateTime end);
}
Run Code Online (Sandbox Code Playgroud)
然后在您的具体实现中:
public class PersonalContact extends Contact<Birthday> {
public Set<Birthday> getEventsWithinPeriod(DateTime start, DateTime end) { ... }
}
Run Code Online (Sandbox Code Playgroud)
这是最好的解决方案,但您有一些替代方案.
解决方案2
您可以更改birthdaysThatAreWithin字段的类型:
Set<Event> birthdaysThatAreWithin = new TreeSet<Event>();
Run Code Online (Sandbox Code Playgroud)
以及更改方法签名:
public Set<Event> getEventsWithinPeriod(DateTime start, DateTime end) {
Run Code Online (Sandbox Code Playgroud)
然后就这样回归 这限制了您,因为您不能Birthday再将事件用作实例.
解决方案3
您还可以将方法签名(在抽象类和具体类中)更改为:
public Set<? extends Event> getEventsWithinPeriod(DateTime start, DateTime end)
Run Code Online (Sandbox Code Playgroud)
而不是改变任何其他东西.这与解决方案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
}
Run Code Online (Sandbox Code Playgroud)
有了第一个解决方案,你就有了这个:
PersonalContact contact = ... ;
Set<Birthday> birthdays = personalContact.getEventsWithinPeriod(start, end);
for (Birthday birthday : birthdays) {
// Do stuff with birthday
}
Run Code Online (Sandbox Code Playgroud)
代码看起来更干净,运行得更好,因为您不必进行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
}
}
Run Code Online (Sandbox Code Playgroud)
如果您有另一个Contact具有Birthday事件的实现,您可以将它们传递给该processBirthdaysFor方法而不进行任何更改.
但是,如果您只需要这些事件并且您不关心调用您的代码中的类型Contact.getEventsWithinPeriod,那么解决方案2和3 绝对是您最好的选择.如果是这种情况,我个人只会使用解决方案2.
| 归档时间: |
|
| 查看次数: |
3416 次 |
| 最近记录: |