2012-11-02 1 views
11

Java에서 "연락처 관리자"를 만들고 있습니다.동일한 인터페이스를 구현하는 두 개의 하위 클래스에 대한 일반적인 메서드 정의

나는 "연락이 개 기본 클래스가라는 슈퍼 클래스 갖는다. PersonalContactBusinessContact

나는이 수업 생일에 의해 구현됩니다 이벤트라는 인터페이스, 회의 (생일에는 DateTime 개체가 1 개 있고 회의에는 시작 및 종료 시간이 두 개가 있음)

개인 연락처에는 의 트리 집합이 있습니다. 생일은입니다. 비즈니스 연락처에는 모임이 있습니다.

지금, 슈퍼 클래스 연락에, 나는 주어진 시간 범위 내의 모든 생일 및/또는 회의의 TreeSet의 반환됩니다 "getEventsWithinPeriod()"라는 추상적 인 방법을 만들려고합니다.

문제는 추상적 인 방법을 알려주는 방법을 모르고 다음에 반환 할 기본 클래스 방법을 알 수 없기 때문입니다.

예를 들어, 이것은 내가 사용 한 코드입니다. ;

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 (날짜 시간, 날짜 시간)과 호환되지?" 현재 시도가 왜 잘못 되었습니까?

+2

왜 '이벤트'인터페이스를 계속 사용하고 싶지 않으십니까? 구현을위한 가시적 인 메소드 목록을 정의하여 코드를 명확하게 만드는 인터페이스의 주요 아이디어.'TreeSet ' –

+0

을 사용하십시오. 나는 완전히 동의합니다. @ Fess - "getEvents ..."가 Events를 반환한다는 것은 분명합니다. 이 경우 제네릭을 사용하는 것은 혼란스럽고 도움이되지 않습니다. –

+0

네, 맞습니다. 나는 그런 식으로 끝내게되었습니다. 인터페이스가 배너 "이벤트"아래에서 동일한 유형으로 통합 할 수있는 방법을 명확하게 이해하지 못했습니다. 당신의 도움을 주셔서 감사합니다! – CodyBugstein

답변

6

세 가지 해결책이 있습니다.

해결 방법 1

첫째, 당신은, 당신의 클래스를 일반적인 할 수 있도록 같은 :

public class PersonalContact extends Contact<Birthday> { 

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

이 최고의 솔루션입니다 : 당신의 구체적인 구현 다음

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

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

그리고 하지만 몇 가지 대안이 있습니다.

당신은 당신의 birthdaysThatAreWithin 필드의 유형을 변경할 수 2

솔루션 :

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

을뿐만 아니라 메소드 서명을 변경

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

을 그처럼 돌아갑니다. 이벤트를 더 이상 Birthday 인스턴스로 사용할 수 없으므로 제한됩니다.

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

을하고 무엇을 변경하지 :

해결 방법 3

당신은이에 (모두 당신의 추상과 구상 클래스에서) 당신의 방법 서명을 변경할 수 있습니다. 이는 솔루션 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 
    } 
} 

을 그리고 당신이 이제까지 Birthday 이벤트가 Contact의 다른 구현이있는 경우, 당신은 변경하지 않고 그 processBirthdaysFor 메소드에 전달할 수 있습니다 : 당신은 또한이 같은 물건을 할 수 있습니다. 당신이 이벤트 만이 필요하고 당신이 유형의 호출 코드에서 어떤 상관 없어 경우

, 당신의 Contact.getEventsWithinPeriod, 다음 솔루션 2와 3은 확실히 당신의 최상의 선택이다. 나는 이것이 상황이라면 개인적으로 단지 해결책 2를 사용할 것입니다.

+0

감사합니다. 솔루션 2가 훌륭하다고 생각합니다. 내 질문은 실제로, 단점은 무엇입니까? 생일 인스턴스로 이벤트를 사용할 수 없다는 것은 무엇을 의미합니까? 나는 무엇을 잃을 까? – CodyBugstein

+1

@Imray 답변을 업데이트하겠습니다. – Brian

+1

@Imray 답변이 업데이트되었습니다. – Brian

10

당신은 어떤 방법을 무시하면 서명이 동일하게 유지해야하며 PersonalContact 클래스의 Set를 돌려 동안 동일하게 유지해야 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

' '이 좋은 연습인지 모르겠습니다. 'T'는 모든 것, 즉 기본 인터페이스와 같아야합니다. 아마도'Contact ' –

+0

@Fess 이미 업데이트되었습니다. –

+0

을 확인하십시오. 오, 좋다. 감사합니다. –

0

제네릭을 사용하는 경우, 당신은 돈 ' 유형을 명시 적으로 지정하려고합니다. 형식을 바인딩 할 수는 있지만 명시 적으로 표시하고 싶지는 않습니다.

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

Contact 방법을 변경하고 변경

PersonalContact 당신이 원하는 걸 얻을해야한다 그

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

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

합니다.

+0

Contact 클래스를 Contact 로 변경해야합니까? – CodyBugstein

관련 문제