Java抽象类:返回派生类的“this”指针

时间:2013-08-13 08:29:37

标签: java design-patterns

我正在尝试使用辅助方法编写一些自定义异常来设置这样的变量:

public class KeyException extends RuntimeException {
    protected String Id;

    protected KeyException(String message) {
        super(message);
    }

    protected KeyException(String message, Throwable cause) {
        super(message, cause);
    }

    public String getId() {
        return keyId;
    }

    public KeyException withId(final String Id) {
        this.Id = Id;
        return this;
    }
}

但是,在我的派生类中,我不能使用“withId”方法,因为它只返回基类 - 无论如何返回“this”指针而不必覆盖每个派生类中的方法?

6 个答案:

答案 0 :(得分:9)

您可以这样做:

public <T extends KeyException> T withId(final String Id) {
    this.Id = Id;
    return (T)this;
}

然后在派生类中,只需将其类型作为类型参数传递。

然而,可能存在设计疏忽。除了构建器模式,我很少看到setter返回对象本身的引用。如果您提供更多背景信息,我们将能够为您提供更多帮助。

答案 1 :(得分:8)

  

无论如何返回“this”指针而不必覆盖每个派生类中的方法?

是的,请看下面的选项1。

您可以通过以下几种方式进行操作:

  1. 将结果投射到派生类

  2. 在子类中重写

  3. 将返回类型更改为void。由于您在对象上调用方法,因此您已经有一个指向它的指针。

答案 2 :(得分:3)

使用以下结构可以使用泛型:

public class ParentType<T extends ParentType<T>> {
    public T withId(String someId) {
        /* Insert other code here */
        return (T) this;
    }
}

public class BranchType<T extends BranchType<T>> extends ParentType<T> {}

public final class LeafTypeA extends BranchType<LeafTypeA> {}

public final class LeafTypeB extends ParentType<LeafTypeB> {}

其中BranchType是一个带有子类的类,而LeafTypeA,LeafTypeB是没有子类的类。

这比其他仿制药解决方案略有改进,因为它可以防止:

public class LeafTypeA extends BranchType<LeafTypeB> {}

因为这不满足类型参数的约束。

答案 3 :(得分:1)

有一种方法可以使用泛型来解决返回子类问题:

// base class

public class Base<T extends Base> {

  private T myself;

  public Base(T myself, Class<T> cls) {
    this.myself = myself;
  }

  public T withSomething() {
    return myself;
  }
}

// subclass

public class SomeSubCls extends Base<SomeSubCls> {

  public SomeSubCls() {
    super(this, SomeSubCls.class);
  }
}

使用此模式new SomeSubCls().withSomething()将返回作为子类实例的对象,而不是父对象。

例如fest assertions使用,请检查this

答案 4 :(得分:1)

如果您有派生类,例如

public class AnotherException extends KeyException {
     ...
}

....然后你可以使用withId ....来简化它。

AnotherException a = new AnotherException ("A");
AnotherException b = (AnotherException) a.withId("ID");

...因为它基本上是同一个对象。你只需要施展它。

答案 5 :(得分:-1)

不幸的是没有。如果你能做到这一点会很好

public this withId(final String Id) { // doesn't work
    this.Id = Id;
    return this;
}

或只是

public this withId(final String Id) { // doesn't work either
    this.Id = Id;
}

或者它会知道“无效”方法是隐式链接的(因为我相信一个正式提案建议)