Java泛型中更简单的方法,可以根据其他两种类型推断返回类型

时间:2016-03-27 04:09:09

标签: java generics interface

我在Java中尝试做的事实上是拥有一个接口,它是两个其他接口的组合(因此它具有来自这两个接口的方法,但它们都没有),以及然后可以一次一个地交换两个子接口,因此当进行改变时,保留来自两个接口之一的所有方法,而来自另一个接口的所有方法被交换为不同的接口。由于泛型正在处理切换,因此无需进行转换以获取新方法或删除旧方法。

因此,我们开始使用接口AA,它是接口LeftARightA的组合,为其提供方法methodLeftA和{{1然后我们调用methodRightA,现在我们有接口selectLeftType(B),它是接口BALeftB的组合,为它提供方法RightAmethodLeftB。使用泛型,这基本上允许我做类似以下的事情:methodRightA

我已经制定了一个可以正常工作的实现,我将在这里进一步展示,但代码非常冗长。只需要执行类型A,B和C.已经有30个文件,要添加D,需要添加16个新文件并编辑17个现有文件。要在此之后添加E,需要添加20个新文件并编辑26个现有文件。因此,虽然这对于少数选项来说是可以接受的,但它会迅速失控,而不仅仅是几个选项。所以我的问题是,是否有一些更简单,更清洁的方法可以做到这一点?

注意:这是使用Java 7构建的,但我对使用Java 8功能的实现持开放态度。

我目前的实施如下(就像我之前说过的那样,很长):

BaseImpl.java

getStartState().methodLeftA().methodRightA().selectLeftType(B).methodLeftB().methodRightA()

Selector.java

package test;

class BaseImpl<CURRENT_INTERFACE> implements Combo<CURRENT_INTERFACE> {

  protected <T extends Combo<?>> T 
      selectLeftTypeBase(Selector<?, ?, ?, ?, ?, ?> selector, Class<T> cls) {
    System.out.println("Switch left type.  New class: " + cls.getSimpleName());
    return selectTypeBase(cls);
  }

  protected <T extends Combo<?>> T 
      selectRightTypeBase(Selector<?, ?, ?, ?, ?, ?> selector, Class<T> cls) {
    System.out.println("Switch right type. New class: " + cls.getSimpleName());
    return selectTypeBase(cls);
  }

  private <T extends Combo<?>> T selectTypeBase(Class<T> cls) {
    try {
      return cls.newInstance();
    } catch (InstantiationException | IllegalAccessException e) {
      e.printStackTrace();
    }
    return null;
  }

  @SuppressWarnings("unchecked")
  public CURRENT_INTERFACE methodLeftA() {
    System.out.println("Left A specific stuff.");
    return (CURRENT_INTERFACE) this;
  }

  @SuppressWarnings("unchecked")
  public CURRENT_INTERFACE methodLeftB() {
    System.out.println("Left B specific stuff.");
    return (CURRENT_INTERFACE) this;
  }

  @SuppressWarnings("unchecked")
  public CURRENT_INTERFACE methodLeftC() {
    System.out.println("Left C specific stuff.");
    return (CURRENT_INTERFACE) this;
  }

  @SuppressWarnings("unchecked")
  public CURRENT_INTERFACE methodRightA() {
    System.out.println("Right A specific stuff.");
    return (CURRENT_INTERFACE) this;
  }

  @SuppressWarnings("unchecked")
  public CURRENT_INTERFACE methodRightB() {
    System.out.println("Right B specific stuff.");
    return (CURRENT_INTERFACE) this;
  }

  @SuppressWarnings("unchecked")
  public CURRENT_INTERFACE methodRightC() {
    System.out.println("Right C specific stuff.");
    return (CURRENT_INTERFACE) this;
  }

}

Util.java

package test;

public final class Selector<
    LEFT_A_TYPE extends LeftA<LEFT_A_TYPE> & Combo<LEFT_A_TYPE>, 
    RIGHT_A_TYPE extends RightA<RIGHT_A_TYPE> & Combo<RIGHT_A_TYPE>, 
    LEFT_B_TYPE extends LeftB<LEFT_B_TYPE> & Combo<LEFT_B_TYPE>, 
    RIGHT_B_TYPE extends RightB<RIGHT_B_TYPE> & Combo<RIGHT_B_TYPE>, 
    LEFT_C_TYPE extends LeftC<LEFT_C_TYPE> & Combo<LEFT_C_TYPE>, 
    RIGHT_C_TYPE extends RightC<RIGHT_C_TYPE> & Combo<RIGHT_C_TYPE>> {

  public static final Selector<AA, AA, BA, AB, CA, AC> A = 
                  new Selector<AA, AA, BA, AB, CA, AC>(
                      AAImpl.class, AAImpl.class, 
                      BAImpl.class, ABImpl.class, 
                      CAImpl.class, ACImpl.class);

  public static final Selector<AB, BA, BB, BB, CB, BC> B = 
                  new Selector<AB, BA, BB, BB, CB, BC>(
                      ABImpl.class, BAImpl.class, 
                      BBImpl.class, BBImpl.class, 
                      CBImpl.class, BCImpl.class);

  public static final Selector<AC, CA, BC, CB, CC, CC> C = 
                  new Selector<AC, CA, BC, CB, CC, CC>(
                      ACImpl.class, CAImpl.class, 
                      BCImpl.class, CBImpl.class, 
                      CCImpl.class, CCImpl.class);

  private final Class<? extends LEFT_A_TYPE> leftATypeClass;
  private final Class<? extends LEFT_B_TYPE> leftBTypeClass;
  private final Class<? extends LEFT_C_TYPE> leftCTypeClass;

  private final Class<? extends RIGHT_A_TYPE> rightATypeClass;
  private final Class<? extends RIGHT_B_TYPE> rightBTypeClass;
  private final Class<? extends RIGHT_C_TYPE> rightCTypeClass;

  private Selector(
      Class<? extends LEFT_A_TYPE> leftATypeClass, 
      Class<? extends RIGHT_A_TYPE> rightATypeClass, 
      Class<? extends LEFT_B_TYPE> leftBTypeClass, 
      Class<? extends RIGHT_B_TYPE> rightBTypeClass, 
      Class<? extends LEFT_C_TYPE> leftCTypeClass, 
      Class<? extends RIGHT_C_TYPE> rightCTypeClass) {

    this.leftATypeClass = leftATypeClass;
    this.leftBTypeClass = leftBTypeClass;
    this.leftCTypeClass = leftCTypeClass;

    this.rightATypeClass = rightATypeClass;
    this.rightBTypeClass = rightBTypeClass;
    this.rightCTypeClass = rightCTypeClass;
  }

  public Class<? extends LEFT_A_TYPE> getLeftATypeClass() {
    return leftATypeClass;
  }

  public Class<? extends LEFT_B_TYPE> getLeftBTypeClass() {
    return leftBTypeClass;
  }

  public Class<? extends LEFT_C_TYPE> getLeftCTypeClass() {
    return leftCTypeClass;
  }

  public Class<? extends RIGHT_A_TYPE> getRightATypeClass() {
    return rightATypeClass;
  }

  public Class<? extends RIGHT_B_TYPE> getRightBTypeClass() {
    return rightBTypeClass;
  }

  public Class<? extends RIGHT_C_TYPE> getRightCTypeClass() {
    return rightCTypeClass;
  }
}

Left.java

package test;

public final class Util {

  private Util() {}

  public static AA getStartState() {
    return new AAImpl();
  }
}

Right.java

package test;

public interface Left<CURRENT_INTERFACE> { }

Combo.java

package test;

public interface Right<CURRENT_INTERFACE> { }

LeftA.java

package test;

public interface Combo<CURRENT_INTERFACE> extends 
    Left<CURRENT_INTERFACE>, 
    Right<CURRENT_INTERFACE> { }

LeftB.java

package test;

public interface LeftA<CURRENT_INTERFACE> extends Left<CURRENT_INTERFACE> {
  public CURRENT_INTERFACE methodLeftA();
  public <T extends Combo<T> & LeftA<T>> T 
    selectRightType(Selector<T, ?, ?, ?, ?, ?> selector);
}

LeftC.java

package test;

public interface LeftB<CURRENT_INTERFACE> extends Left<CURRENT_INTERFACE> {
  public CURRENT_INTERFACE methodLeftB();
  public <T extends Combo<T> & LeftB<T>> T 
    selectRightType(Selector<?, ?, T, ?, ?, ?> selector);
}

RightA.java

package test;

public interface LeftC<CURRENT_INTERFACE> extends Left<CURRENT_INTERFACE> {
  public CURRENT_INTERFACE methodLeftC();
  public <T extends Combo<T> & LeftC<T>> T 
    selectRightType(Selector<?, ?, ?, ?, T, ?> selector);
}

RightB.java

package test;

public interface RightA<CURRENT_INTERFACE> extends Right<CURRENT_INTERFACE> {
  public CURRENT_INTERFACE methodRightA();
  public <T extends Combo<T> & RightA<T>> T 
    selectLeftType(Selector<?, T, ?, ?, ?, ?> selector);
}

RightC.java

package test;

public interface RightB<CURRENT_INTERFACE> extends Right<CURRENT_INTERFACE> {
  public CURRENT_INTERFACE methodRightB();
  public <T extends Combo<T> & RightB<T>> T 
    selectLeftType(Selector<?, ?, ?, T, ?, ?> selector);
}

AA.java

package test;

public interface RightC<CURRENT_INTERFACE> extends Right<CURRENT_INTERFACE> {
  public CURRENT_INTERFACE methodRightC();
  public <T extends Combo<T> & RightC<T>> T 
    selectLeftType(Selector<?, ?, ?, ?, ?, T> selector);
}

AAImpl.java

package test;

public interface AA extends Combo<AA>, LeftA<AA>, RightA<AA> { }

AB.java

package test;

final class AAImpl extends BaseImpl<AA> implements AA {

  @Override
  public <T extends Combo<T> & LeftA<T>> T 
      selectRightType(Selector<T, ?, ?, ?, ?, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftATypeClass());
  }

  @Override
  public <T extends Combo<T> & RightA<T>> T 
      selectLeftType(Selector<?, T, ?, ?, ?, ?> selector) {
    return selectLeftTypeBase(selector, selector.getRightATypeClass());
  }

}

ABImpl.java

package test;

public interface AB extends Combo<AB>, LeftA<AB>, RightB<AB> { }

AC.java

package test;

final class ABImpl extends BaseImpl<AB> implements AB {

  @Override
  public <T extends Combo<T> & LeftA<T>> T 
      selectRightType(Selector<T, ?, ?, ?, ?, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftATypeClass());
  }

  @Override
  public <T extends Combo<T> & RightB<T>> T 
      selectLeftType(Selector<?, ?, ?, T, ?, ?> selector) {
    return selectLeftTypeBase(selector, selector.getRightBTypeClass());
  }

}

ACImpl.java

package test;

public interface AC extends Combo<AC>, LeftA<AC>, RightC<AC> { }

BA.java

package test;

final class ACImpl extends BaseImpl<AC> implements AC {

  @Override
  public <T extends Combo<T> & LeftA<T>> T 
      selectRightType(Selector<T, ?, ?, ?, ?, ?> selector) {
    return selectLeftTypeBase(selector, selector.getLeftATypeClass());
  }

  @Override
  public <T extends Combo<T> & RightC<T>> T 
      selectLeftType(Selector<?, ?, ?, ?, ?, T> selector) {
    return selectRightTypeBase(selector, selector.getRightCTypeClass());
  }

}

BAImpl.java

package test;

public interface BA extends Combo<BA>, LeftB<BA>, RightA<BA> { }

BB.java

package test;

final class BAImpl extends BaseImpl<BA> implements BA {

  @Override
  public <T extends Combo<T> & LeftB<T>> T 
      selectRightType(Selector<?, ?, T, ?, ?, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftBTypeClass());
  }

  @Override
  public <T extends Combo<T> & RightA<T>> T 
      selectLeftType(Selector<?, T, ?, ?, ?, ?> selector) {
    return selectLeftTypeBase(selector, selector.getRightATypeClass());
  }

}

BBImpl.java

package test;

public interface BB extends Combo<BB>, LeftB<BB>, RightB<BB> { }

BC.java

package test;

final class BBImpl extends BaseImpl<BB> implements BB {

  @Override
  public <T extends Combo<T> & LeftB<T>> T 
      selectRightType(Selector<?, ?, T, ?, ?, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftBTypeClass());
  }

  @Override
  public <T extends Combo<T> & RightB<T>> T 
      selectLeftType(Selector<?, ?, ?, T, ?, ?> selector) {
    return selectLeftTypeBase(selector, selector.getRightBTypeClass());
  }

}

BCImpl.java

package test;

public interface BC extends Combo<BC>, LeftB<BC>, RightC<BC> { }

CA.java

package test;

final class BCImpl extends BaseImpl<BC> implements BC {

  @Override
  public <T extends Combo<T> & LeftB<T>> T 
      selectRightType(Selector<?, ?, T, ?, ?, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftBTypeClass());
  }

  @Override
  public <T extends Combo<T> & RightC<T>> T 
      selectLeftType(Selector<?, ?, ?, ?, ?, T> selector) {
    return selectLeftTypeBase(selector, selector.getRightCTypeClass());
  }

}

CAImpl.java

package test;

public interface CA extends Combo<CA>, LeftC<CA>, RightA<CA> { }

CB.java

package test;

final class CAImpl extends BaseImpl<CA> implements CA {

  @Override
  public <T extends Combo<T> & LeftC<T>> T 
      selectRightType(Selector<?, ?, ?, ?, T, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftCTypeClass());
  }

  @Override
  public <T extends Combo<T> & RightA<T>> T 
      selectLeftType(Selector<?, T, ?, ?, ?, ?> selector) {
    return selectLeftTypeBase(selector, selector.getRightATypeClass());
  }

}

CBImpl.java

package test;

public interface CB extends Combo<CB>, LeftC<CB>, RightB<CB> { }

CC.java

package test;

final class CBImpl extends BaseImpl<CB> implements CB {

  @Override
  public <T extends Combo<T> & LeftC<T>> T 
      selectRightType(Selector<?, ?, ?, ?, T, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftCTypeClass());
  }

  @Override
  public <T extends Combo<T> & RightB<T>> T 
      selectLeftType(Selector<?, ?, ?, T, ?, ?> selector) {
    return selectLeftTypeBase(selector, selector.getRightBTypeClass());
  }

}

CCImpl.java

package test;

public interface CC extends Combo<CC>, LeftC<CC>, RightC<CC> { }

所有这些代码都允许我进行以下操作:

package test;

final class CCImpl extends BaseImpl<CC> implements CC {

  @Override
  public <T extends Combo<T> & LeftC<T>> T 
      selectRightType(Selector<?, ?, ?, ?, T, ?> selector) {
    return selectRightTypeBase(selector, selector.getLeftCTypeClass());
  }

  @Override
  public <T extends Combo<T> & RightC<T>> T 
      selectLeftType(Selector<?, ?, ?, ?, ?, T> selector) {
    return selectLeftTypeBase(selector, selector.getRightCTypeClass());
  }

}

0 个答案:

没有答案