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

问题描述 投票:0回答:1

抱歉这个标题,但这个问题很难用简单的语言解释。 上课:

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 类定义的所有者,因此我不可能更改它。不过我可以以某种方式延长。 我可以做什么来强制这种关系?

java generics interface
1个回答
0
投票

由于类型擦除,我认为您无法使用纯泛型来做到这一点......但是根据您愿意编写多少代码来实现您的目标,这可能是一个潜在的(尽管很混乱)解决方案。在不了解更多细节的情况下,很难说这是否能涵盖您的所有用例。

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);
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.