2011-09-28 2 views
1

반환 형식에서 제네릭을 사용하는 경우 부모 클래스를 확장하는 데 어려움이 있습니다 다음 예제와 같습니다.Java에서 일반 반환 형식을 사용하는 메서드 재정의

알다시피 제네릭 없이는 다음 예제는 정상적으로 컴파일되지만 유형이 Object 여야하므로 유형 안전하지 않습니다.

제가 참조 할 수있는 명확한 해결책 (또는 패턴 또는 조언, 도움이 될만한 것이 있습니까?)이 있습니까?

class AbstractReader<T>{ 
    public abstract T readNext(); 
} 
class ByteArrayReader extends AbstractReader<byte[]>{ 
    @Override 
    public byte[] readNext(){ /*...*/ } 
} 
class StringReader extends ByteArrayReader { 
    @Override 
    public String readNext() { 
     /* The return type is incompatible 
      with ByteArrayReader.readNext()! */ 
     return new String(bytes); 
    } 
} 

답변

2

당신은 상속 대신 데코레이터 디자인 패턴을 사용할 수 있습니다 여기

class StringReader { 
    private ByteArrayReader bar; 

    public StringReader(ByteArrayReader bar) { 
     this.bar = bar 
    } 

    public String readNext() { 
     return new String(this.bar.readNext()); 
    } 
} 
+0

귀하의 조언에 감사드립니다. 나는 또한 작곡을 사용하는 것이이 경우에 최선이라고 생각한다. 그러나 StringReader와 ByteArrayReader가 여러 메서드를 공유하면 Decorator는 다음과 같은 반복 코드를 갖게됩니다. 'ReturnType someMethod (Arg args) {byteArray.someMethod(); }' 불가피 할 것입니까? – nephilim

+0

예, 반복적 인 코드가 발생할 수 있지만 더 깨끗한 구현이 가능합니다! – claymore1977

3

문제는 StringReaderByteArrayReader을 확장 거기는 이해가되지 않는다는 것입니다. 당신은 상속과 구성을 혼동하고 있습니다.

ByteArrayReader에서 StringReader 상속 당신이 그것을 그것이 byte[] 반환하는 readNext 방법이있다라는 계약을 이행 할 것을 말하고있다.

은 당신이 정말로 원하는 것은 상속보다는 구성을 사용할 수 있습니다 :

class StringReader extends AbstractReader<String> { 
    private AbstractReader<byte[]> downstream; 

    public StringReader(AbstractReader<byte[]> downstream) { 
     this.downstream = downstream; 
    } 

    public String readNext() { 
     return new String(downstream.readNext()); 
    } 
} 

StringReaderAbstractReader<String> 계약을 이행하고, 다운 스트림 AbstractReader<byte[]>의 관점에서 구현됩니다. 명시 적으로는 ByteArrayReader이 필요하지 않습니다. 이전의 AbstractReader<byte[]>은 작동합니다.

+0

감사합니다. 나는 StringReader가 AbstractReader 이라는 것에 동의한다. (그리고 코드가 성공적으로 컴파일되면 다형성이 올바르게 작동하지 않을 것입니다.) 그러나 StringReader와 ByteArrayReader가 많은 함수를 공유하면'ReturnType someMethod (Args args) {byteArrayReader.someMethod (args); }'반복적으로. 이상하지 않니? – nephilim

+1

예, 조금 이상합니다. 여기서 당신이 근본적으로하고있는 것은'AbstractReader '을'AbstractReader '에 매핑하는 것입니다. 그래서 (불행히도) 모든 메소드를 구현해야합니다. 형식 매개 변수를 매핑하는 간단한 방법이있는 경우 리플렉션을 사용하여 달성 할 수 있지만 천천히, 못 생기고 완전히 유지할 수 없습니다. –

0

귀하의 문제는 귀하에게 이것이 귀하가 상속을 잘 활용하지 않는다는 것을 말하고 있습니다. StringReader는 확실히 ByteArrayReader와 is-a 관계가 없습니다. 둘 사이에 공통된 기능이 있다면 이는 구현 세부 사항 일뿐입니다. 이러한 공통 코드는 모두 AbstractReader로 푸시되어야하며이 둘에서 직접 확장해야합니다. 그런 다음 추상 클래스에는 해당 하위 클래스에 공통적 인 코드가 올바르게 포함되어 있으며 동일한 객체 (아마도 Reader)의 구현 외에도 StringReader와 ByteArrayReader는 올바르게 관련이 없습니다.

+0

감사합니다. 샘플 코드가 혼란 스럽지만 답변에서 문제를 찾을 수있었습니다. – nephilim