2014-09-23 3 views
0

아이 빌더 전달 . 현재 그것은 Base의 인스턴스를 반환하고 methodA()Base 클래스에 존재하지 않는다는 오류를주는 것으로 보입니다.내가 뭔가를해야 경우가

GenericTypes의 일부 사례를이 경우 원하는 내용으로 보았습니다. 그러나 아직 구현하지 못했습니다. 모든 예제/포인터/링크 크게 감사하겠습니다.

감사합니다.

+0

ChildA로 전송하려고 했습니까? – lifus

답변

1

ChildA으로 정의되었지만 getSiblingBase을 반환하므로이 기능이 작동하지 않습니다. 이 Base 참조가 ChildA 개체를 가리 키지 만 명시 적 캐스팅을 수행하거나 Base 유형을 일반화해야합니다. 이 특별한 경우

, 당신은 단순히 getSibling를 오버라이드 (override) 할 수 있습니다 : ChildB 같은 클래스의 많은 생각이있는 경우

class ChildB extends Base { 
    public ChildB(ChildA sibling) { 
    super(sibling); 
    } 

    @Override 
    public ChildA getSibling() { 
    return (ChildA) super.getSibling(); 
    } 
} 

이 잘 확장하지 않을 것입니다. 또한 ChildB은 형제이므로 ChildA 만 포함하도록 제한됩니다.


편집 :

항상 당신이 그것을 대체 할 수 있습니다 일반 수 Base 클래스를 필요로하지 않는 당신을 가정 childB

좋아하지 않을 수 있습니다 :

class ChildB <T extends Base> extends Base { 
    public ChildB(T sibling) { 
     super(sibling); 
    } 


    @Override 
    @SuppressWarnings("unchecked") 
    public T getSibling() { 
     return (T) super.getSibling(); 
    } 
} 

다음과 같이 지정하십시오 :

brother = new ChildB<ChildA>(this); 
+0

내 경우에 대한이 솔루션의 문제점은 ChildB가 Base의 다른 하위 클래스에 포함될 수 있으므로 getSibling이이를 리턴해야한다는 것입니다. 즉, 항상 아이가 아닐 수도 있습니다. – SS44

+0

오케이, 두 번째 옵션은 어떻습니까? – lifus

+0

도움을 주셔서 감사합니다. 해결책을 수락했습니다. – SS44

1

주조로하지 않는 한, 당신은 당신이 원하는 것을 할 수 없습니다

var child = new ChildA() 
     .getBrother() // ChildB 
      .someMethodX() // void 
      .someMethodY() // compile error 
      .getSibling() // compile error (someMethodY = void), Base 
     .methodA() // compile error, methodA does not exists on Base 
     .methodB() // idem. 

을 나는 당신이 그 일을하는 두 가지 방법을 제안한다 :

  • Base에 제네릭 형식, Base 할 수 있도록 Base이 아닌 this을 하위 유형으로 반환하십시오. ChildABase으로 확장되고 두 가지 방법이 ChildA::setFoobar, Base::setSaxon 인 경우 일괄 처리로 인해 builder.setSaxon("A").setFoobar("B")이 가능합니다.

    public class Base<B extends Base<B>> { 
        protected abstract B self(); 
        public <C extends Base<C>> B setSibling(Base<C> base) { 
        this.sibling = base; 
        return self(); // or (B)this 
        } 
    }  
    public class ChildA extends Base<ChildA> { 
        protected ChildA self() {return this;} 
    } 
    public class ChildB extends Base<ChildB> {} 
    

    그리고이 작동합니다 다음 self 방법은 각 setXXX 방법 (B)this에 캐스트를 피할 수

    ChildA a = new ChildA().setSibling(new ChildB().setSibling(new ChildA())); 
    

    .

  • B 용 빌더 래퍼를 사용 : 그 중간 개체 ChildBBuilder를 돌아 "최종"방법 getSibling()이 속하는 ChildAChildB의 새로운 인스턴스를 연결하고, 체인 계속 객체를 반환 :

    public class ChildA extends Base{ 
        private ChildB brother; 
        public ChildBBuilder getBrother() { 
        return new ChildBBuilder() { 
         public ChildA getSibling() { 
         ChildA.this.brother = create(); 
         return ChildA.this; 
         } 
        }; 
        } 
    } 
    
    public class ChildBBuilder { 
        public ChildBBuilder(ChildA parent) { 
        this.parent = parent; 
        } 
        ... setter ... 
    
        public ChildB create() { 
        return new ChildB(); 
        } 
    
        public ChildA getSibling() { 
        throw new UnsupportedOperationException(); 
        } 
    } 
    

    ChildBBuilder은 기본 구현이 실패하는 일부 getSibling 조작을 허용하는 독립 빌더입니다. 이 경우를 처리하기 위해 익명 추상 클래스를 만듭니다.

저는 이미 "기본 작성기"가있는 첫 번째 경우에 일부 프로젝트에서 사용되었습니다.

두 번째 경우에는 사용하지 않았습니다. 일부 작업에 대해 DSL을 만들려고 시도하는 경우 DSL이 유용 할지라도 그것이 가치있는 일을하는 것은 너무 많을 수 있음을 잊지 마십시오.

Java 8로 작업하는 경우 패턴을 순수 추상 구현 (see my answer here)으로 확장 할 수 있습니다.

관련 문제