データのメタタイプを表す Type インターフェイスがあります。パラメータは、データを表すために使用される 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()
参照する方法はありますか? それは、コードを私が望むよりもはるかに複雑にしています。Type
Value
システム内の数値を表す単純な型を想像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();
そうすれば、特定の Type の Java 表現を変更する必要がある場合 (たとえば、上記のコードのNumericType<Number>
代わりに作成NumericType<BigDecimal>
したい場合は、コンパイル時に失敗します。しかしValue
、そのget()
メソッド宣言が境界の境界を参照できるType
ように記述する方法パラメータ?Value<J, Type<J>>
読むのは本当に厄介です:
Value<BigDecimal, NumericType> foo;
もっと良い方法があることを願っています。