我有一个案例,我有类似的东西:
public abstract class Base{
private Base sibling;
public Base( Base sibling ){
this.sibling = sibling;
}
public Base getSibling(){
return this.sibling;
}
}
public class ChildA extends Base{
private ChildB brother;
public ChildA(){
this.brother = new ChildB( this );
}
public ChildB getBrother(){ return this.brother }
public void methodA(){ ... }
public void methodB(){ ... }
}
public class ChildB extends Base{
public childB someMethodX(){ ... }
public childB someMethodY(){ ... }
}
现在我需要它,以便在做类似的事情时:
var child = new ChildA()
.getBrother()
.someMethodX()
.someMethodY()
.getSibling()
.methodA()
.methodB()
.getSibling()
让我回到ChildA
的范围内。目前,它似乎正在返回Base
的一个实例,并在methodA()
课程中向我提供Base
不存在的错误。
我已经看过GenericTypes的一些案例,因为在这种情况下可能是我想要的,但我还是很难实现它。任何示例/指针/链接都将非常感激。
感谢。
答案 0 :(得分: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
可以返回this
作为子类型而不是Base
。如果ChildA
扩展Base
,使用两种方法ChildA::setFoobar
,Base::setSaxon
,则可以执行:builder.setSaxon("A").setFoobar("B")
,因为通用。{/ p>
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> {}
这样可行:
ChildA a = new ChildA().setSibling(new ChildB().setSibling(new ChildA()));
self
方法将避免在每个(B)this
方法中转换为setXXX
。
使用B的构建器包装器:返回一个中间对象ChildBBuilder
,其中&#34; final&#34;方法getSibling()
将ChildB
的新实例与其所属的ChildA
相关联,并返回该对象以继续链:
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操作,其默认实现失败。我们创建一个匿名抽象类来处理这种情况。
我已经在我的一些项目中使用了第一个案例,使用了&#34; base builder&#34;。
对于第二种情况,我从未使用过它。如果你正在尝试为你的一些工作创建一个DSL,不要忘记,即使它很好也可能是它的价值太多了。
如果您正在使用Java 8,则可以将模式扩展为纯抽象实现:see my answer here。
答案 1 :(得分:1)
这不起作用,因为在methodA
中定义了ChildA
,但getSibling
返回Base
引用。虽然此Base
引用恰好指向ChildA
对象,但您应该执行显式转换或概括Base
类型。
在这种特殊情况下,您可以简单地覆盖getSibling
:
class ChildB extends Base {
public ChildB(ChildA sibling) {
super(sibling);
}
@Override
public ChildA getSibling() {
return (ChildA) super.getSibling();
}
}
如果有很多像ChildB
这样的课程,那么这不会很好地扩展。此外,ChildB
被限制为仅包含ChildA
兄弟姐妹。
编辑:
它可能并不总是childB
好吧,假设您不需要Base
类是通用的,您可以将其替换为:
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);