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)
他には何も変更しません。Birthday
これにはソリューション2と同じ問題があり、イベントをキャストせずにインスタンスとして使用することはできません。
編集: 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を使用します。