如何强制特定实现来实现给定的接口

时间:2014-03-21 10:02:39

标签: java generics interface core

对不起标题,但用简单的话很难解释问题。 上课:

public abstract class SimpleAssembler
    <DI extends IIdBean, DO extends DomainObject, VO extends VOBase>
    implements Assembler<DI, DO, VO> {...}

我想强制DO和DI之间的连接,以便DO必须实施DI。我试图让它像这样工作:

    public abstract class SimpleAssembler
    <DI extends IIdBean, DO extends DomainObject & DI, VO extends VOBase>
    implements Assembler<DI, DO, VO> {...}

但这不会编译。另一个问题是我不是DomainObject类定义的所有者,因此我无法更改它。我可以延伸但不知何故。 我该怎么做才能强迫这种关系?

1 个答案:

答案 0 :(得分:0)

我认为你不能因为类型擦除而使用纯Generics做到这一点......但是根据你为实现目标而愿意写的多少,这可能是一种潜力(尽管如此)凌乱的解决方案。在不了解更多细节的情况下,很难说这是否会涵盖您的所有用例。

import java.io.Serializable;

interface Assembler<DI, DO, VO> {
  /* ??? not given ??? */
  void acceptsBean(DI bean);
  void acceptsDomain(DO domain);
}


interface VOBase {
  /* ??? not given ??? */
}


interface IIdBean<T extends Comparable<T> & Serializable> {
  /* as given */
}


class DomainObject {
  /* third-party class, cannot be altered */
}


abstract class AbstractIdBeanDomainObject
  <T extends Comparable<T> & Serializable, I extends IIdBean<T>> 
  extends DomainObject {

  private final Class<I> interfaceType;

  protected AbstractIdBeanDomainObject(Class<I> beanInterface) {
    super();
    if (beanInterface == null 
          || !beanInterface.isAssignableFrom(this.getClass())) {
      throw new IllegalStateException(
          "This class must implement the specified bean type.");
    }
    interfaceType = beanInterface;
  }

  final I asBean() {
    return interfaceType.cast(this);
  }
}

interface IIntIdBean extends IIdBean<Integer> {
  /* ... */
}

class MyIntIdBean implements IIntIdBean {
  /* ... */
}

class MyIntDomainObject extends AbstractIdBeanDomainObject<Integer, IIntIdBean> {
  MyIntDomainObject() {
    super(IIntIdBean.class);
  }
}

class NotSoSimpleAssembler
  <T extends Comparable<T> & Serializable, 
   DI extends IIdBean<T>,
   DO extends AbstractIdBeanDomainObject<T, DI>,
   VO extends VOBase>
  implements Assembler<DI, DO, VO> {

  @Override
  public void acceptsBean(DI bean) { }

  @Override
  public void acceptsDomain(DO domain) { acceptsBean(domain.asBean()); }
}

public class StackOverflow22555608 {
  public static final void main(String[] args) {

    VOBase base = new VOBase() { /* ??? */ };

    IIntIdBean idBean = new MyIntIdBean();

    AbstractIdBeanDomainObject<Integer, IIntIdBean> domainObj =
      new MyIntDomainObject();

    Assembler<IIntIdBean, AbstractIdBeanDomainObject<Integer, IIntIdBean>, VOBase> asm =
      new NotSoSimpleAssembler<>();
    asm.acceptsBean(idBean);
    asm.acceptsDomain(domainObj);
  }
}