3

我有一个表示数据元类型的接口类型。该参数指示将用于表示数据的 Java 类型:

public interface Type<J> {
    boolean isAssignableFrom(@NotNull Type ts);

    /**
     * Gets the Java class of the representation of this type.
     */
    Class<? extends J> getValueType();
}

我还有一个代表该类型实例的值接口:

public interface Value<T extends Type> {
    <E> E get();

    @NotNull
    T getType();
}

我想要的是让Value接口强制执行在接口上声明的参数Type。换句话说,我希望该get()方法声明其返回类型必须在<J>. <J>但是如果不添加到Value界面中,我无法想出任何方法来做到这一点:

public interface Value<J, T extends Type<J>> {
    J get();

    @NotNull
    T getType();
}

有没有办法在不将其添加到接口的情况下get()引用它的有界参数?它使代码真的比我想要的复杂得多。TypeValue

所以想象一下NumericType哪个是表示系统中数字的简单类型(还有更复杂的动态类型,除了运行时不存在,这就是元编程的乐趣):

/** A static type representing some kind of number. */
public class NumericType implements Type<BigDecimal>
{
    public static final NumericType NUMERIC_TYPE = new NumericType();


    public boolean isAssignableFrom(@NotNull Type t)
    {
        // logic here
    }

    public Class<BigDecimal> getValueType() {
        return BigDecimal.class;
    }
}

它告诉调用者用于在系统中表示此类型的 Java 类型。如果我声明一个值NumericType

Value<NumericType> foo;

希望能够拥有始终返回 BigDecimal 的编译时安全get()性:

BigDecimal bar = foo.get();

这样,如果我需要更改给定类型的 Java 表示形式(例如,我想制作NumericType<Number>而不是NumericType<BigDecimal>上面的代码将在编译时失败。但是我如何编写Value使其get()方法声明可以引用有界的Type边界参数?这Value<J, Type<J>>东西读起来真的很笨拙:

Value<BigDecimal, NumericType> foo;

我希望有更好的方法。

4

2 回答 2

0

我确定。在 Java 中不可能做到这一点。此外,如果感兴趣的是隐藏给定 NumericType 使用 BigDecimal 作为内部表示,则使用专用对象实现所需操作的完整抽象会更简单、更健壮。如果仅使用这些操作来操作对象,则可以更改内部表示,以便唯一的更改是此类的内部:

  1. 它允许精确定义所需的操作
  2. 由于所需的操作集减少,它允许轻松调整内部表示。

它是基本的 OOP 概念和 KISS 原则(保持简单,愚蠢)。

class NumericType {
  private int value;
  public NumericType(int initial) {...}
  public NumericType add(NumericType operand) {...}
  ...
}

那么它可以像这样使用

NumericType bar = new NumeicType(1);
bar = bar.add(new NumericType(1));
于 2013-11-08T20:09:31.857 回答
0

这就是发明通配符的目的。使用“?扩展”通配符: public interface Value<J, T extends Type<? extends J>> {...}

于 2013-11-12T18:10:04.883 回答