2012-11-02 22 views
11

Java'da "Kişi Yöneticisi" oluşturuyorum.Aynı arabirimi uygulayan iki alt sınıf için genel bir yöntem tanımlama

ben "İletişim iki temel sınıfları vardır denilen bir üst sınıfı var;. personalcontact ve BusinessContact

Ben sınıflar Doğum tarafından uygulanan Olay denilen bir arayüz, ve Toplantı. (Toplantının, bir başlangıç ​​ve bitiş zamanı için iki tane varsa, bir DateTime nesnesi içerir)

Kişisel İrtibat, 'un bir Ağacı Setini içerir ve BusinessContact, Toplantıları bir kümesine sahiptir.

Şimdi, üst sınıf Contact yılında, ben belirli bir zaman dilimi içindeki tüm doğum günleri ve/veya toplantılar TreeSet dönecektir "getEventsWithinPeriod()" adlı soyut bir yöntem oluşturmak istiyorum.

Sorun şu ki, soyut yönteme nasıl anlatacağımı bilmiyorum ve sonra temel sınıf, ne döndürmesi gerektiğini anlatıyor.

Örneğin, bu, 'da kullandığım koddur;

public abstract Set<Event> getEventsWithinPeriod(DateTime start, DateTime end);

Ve personalcontact içinde

;

public Set<Birthday> getEventsWithinPeriod(DateTime start, DateTime end){ 

     Set<Birthday> birthdaysThatAreWithin = new TreeSet<Birthday>(); 
     //CODE 
     return birthdaysThatAreWithin; 

Ancak derleyici, diyordum Set<Birthday> bir hata alıyorum;

kullanıyorum gereken doğru terimler ve iadeler nelerdir "döndürme türü Contact.getEventsWithinPeriod (DateTime, DateTime) ile uyumsuz"? Benim şimdiki denemem neden yanlış?

+2

Neden "Olay" arabirimini kullanmaya devam etmek istemiyorsunuz? Uygulama için görünür yöntemin listesini tanımlayarak, kodun anlaşılması için arabirimin ana fikri.Sadece "TreeSet " –

+0

kullanın. Tam bir anlaşma yapıyorum, @ Fess - "getEvents ..." olayları döndürdüğü açıkça görünüyor, öyle değil mi? Bu durumda jeneriklerin kullanımı sadece kafa karıştırıcı ve yararsızdır. –

+0

Evet siz haklısınız, bu şekilde bitirdim. Arabirimin, "Etkinlikler" başlığı altında her iki sınıfı aynı tür olarak birleştirmek için nasıl kullanılabileceğini anlayamadım. Yardım ettiğin için teşekkür ederim! – CodyBugstein

cevap

6

3 çözümünüz var.

Çözüm 1

İlk olarak, dersleriniz jenerik yapabilirsiniz gibi:

public class PersonalContact extends Contact<Birthday> { 

    public Set<Birthday> getEventsWithinPeriod(DateTime start, DateTime end) { ... } 
} 

Bu en iyi çözüm şudur: Beton uygulanmasında sonra

public abstract class Contact<E extends Event> { 
    // ... 

    public abstract Set<E> getEventsWithinPeriod(DateTime start, DateTime end); 
} 

Ve ama bazı alternatifleriniz var.

Sen birthdaysThatAreWithin alanın türünü değiştirebilir 2

Çözüm:

Set<Event> birthdaysThatAreWithin = new TreeSet<Event>(); 

yanı sıra yöntem imzası değiştirin:

public Set<Event> getEventsWithinPeriod(DateTime start, DateTime end) { 

ve bunu böyle döner. Bu işlem sizi kısıtlar, çünkü artık etkinlikleri Birthday örneği olarak kullanamazsınız.

public Set<? extends Event> getEventsWithinPeriod(DateTime start, DateTime end) 

ve başka bir şey değişmez:

Çözüm 3

Ayrıca buna (hem soyut ve somut sınıfın içinde) yöntemi imzası değiştirebilir. Bu, çözüm 2 ile aynı sorunu yaşıyor, olayları, bunları kullanmadan Birthday örnekleri olarak kullanamazsınız.

Düzenleme: downsides 2 ve 3 için döküm gerektirecektir. Örneğin: İlk çözümü ile

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 
} 

, bu olurdu:

PersonalContact contact = ... ; 
Set<Birthday> birthdays = personalContact.getEventsWithinPeriod(start, end); 
for (Birthday birthday : birthdays) { 
    // Do stuff with birthday 
} 

kod temizleyici görünür ve instanceof kontrolleri yapmak zorunda değilsiniz çünkü don emin olmak için daha iyi çalışır ClassCastException'u al.

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 
    } 
} 

Ve hiç Birthday olayları vardır Contact başka uygulama varsa, herhangi bir değişiklik yapmadan bu processBirthdaysFor yönteme onları geçebilir: Ayrıca böyle şeyler olabilir. Yalnızca olayları ihtiyaç ve türleri çağıran kodda ne umursamazsak Ancak

, senin Contact.getEventsWithinPeriod ardından çözümler 2 ve 3 kesinlikle en iyi bahisler vardır. Durum böyle olsaydı, kişisel olarak sadece çözüm 2'yi kullanırdım.

+0

Teşekkürler, Çözüm 2'nin harika olacağını düşünüyorum. Benim sorum şu ki, pratik olarak ne dezavantajı nedir? Olayları Doğum Günü örnekleri olarak kullanamayacağım ne anlama geliyor? Ne kaybederim? – CodyBugstein

+1

@Iray Yanıtımı güncelleyeceğim – Brian

+1

@Iray Yanıtla güncellendi, bir göz atın. – Brian

10

herhangi yöntemi geçersiz kılmasını, size imza aynı kalmalıdır ve personalcontact sınıfında yer alan dönüş sırasında aynı kalmalıdır 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; 
    } 
} 
+0

''ün iyi bir uygulama olup olmadığını bilmiyorum. Çünkü T 'her şey olmalı, onun gibi varsayılan arayüz. belki <İrtibat ' –

+0

@Fess Zaten güncellenmiş. Lütfen –

+0

'u kontrol edin, iyiyim, teşekkürler –

0

Generics'i kullanırken, 'don t türünü açıkça belirtmek istiyorum. Türü bağlayabilirsiniz, ancak açık olmak istemezsiniz.

public abstract Set<T extends Event> getEventsWithinPeriod(DateTime start, DateTime end); 

için Contact yöntemini değiştirme ve değişiklik

PersonalContact istediğini elde GEREKEN O

public Set<T extends Event> getEventsWithinPeriod(DateTime start, DateTime end){ 

     Set<T> birthdaysThatAreWithin = new TreeSet<Birthday>(); 
     //CODE 
     return birthdaysThatAreWithin; 
} 

için.

+0

İletişim sınıfını sonra mı değiştirmem gerekiyor? – CodyBugstein

İlgili konular