typedef

時々ふと思うのですが、Java にも typedef のようなものが欲しいです。

クラスの各属性の内容を表すような論理型を実装時にも手軽に表現できればコンパイルによるチェックをさらに厳しくできるのではないかと思ったりします。
たとえば、ある「注文」クラスを一意に特定する ID があり、それとは別に「注文」クラスには個数や金額を表す項目があるとします。
そしてそれらの値はすべて Integer として実装されているとします。

ここで、「注文」の個数と金額を更新する以下のシグネチャを持つメソッドがあるとします。

public void updateOrder( Integer orderId, Integer quantity, Integer amount ) {
  :
  :
}

このメソッドを呼び出す場合、以下のようになります。

Integer orderId = ....
Integer quantity = ....
Integer amount = ....
  :
  :
updateOrder( orderId, quantity, amount );

このメソッドが持つ各引数の型は同じであるため、もし引数の順番を間違えたとしてもコンパイルは通ってしまいます。

updateOrder( orderId, amount, quantity );

各引数の順番を間違えた場合にコンパイルエラーとするには、たとえ実際には同じ整数型であっても、それぞれの引数の型に意味付けを行い型による制約を課すぐらいしかありません。

public class OrderId extends Integer {
  :
}

public class Quantity extends Integer {
  :
}

public class Amount extends Integer {
  :
}
public void updateOrder( OrderId orderId, Quantity quantity, Amount amount ) {
  :
}

上記のようにすればそれぞれの引数に設定すべき値として意味のある型をつけることができます。
しかし、この方法では新たな属性が増えるたびに型を定義しなければいけません。属性ができるたびに型を定義するのはさすがに煩雑です。
そこで、もし Java に typedef があれば以下のようなことができるのではないでしょうか?

public class Order {
  public typedef Integer Id;
  public typedef Integer Quantity;
  public typedef Integer Amount;

  public Id getId() {
    :
  }

  public Quantity getQuantity() {
    :
  }

  public Amount getId() {
    :
  }
}
public void updateOrder( Order.Id orderId, Order.Quantity quantity, Order.Amount amount ) {
  :
}

上記のように typedef を利用して手軽に型の定義が行なえれば、わざわざクラスを作る必要もありませんし、手軽に型による制約を行なうことができます。
また、クラスの中で型の定義が行なえれば、「注文」のID値のようにその型が属する対象が明確になるという利点もあります。

ただし、上記の Quantity や Amount 等は 「注文」にのみ属するものではないので、Order クラス内で定義しているのは正しくないと思います。Quantity や Amount のような複数のクラスに関係するような型を定義するうまい方法があればよいのですが、思いつきません。

ほかにも、型変換等の問題もあったりします。

Quantity quantity = 5;
Amount amount = 100;

// 合計金額を求める
??? = quantity * amount;

Quantity * Amount のような演算を行なった場合の結果値の型は何になるのが正しいのかということや、quantity = 5 のような上位の型の値を代入可能なのか?といったことなどが問題として考えられます。このあたりも未考慮です・・・orz


追伸:
Quantity や Amount はなくても Order.Id のような型は欲しいですね。これがあると「注文」の ID と 「ユーザ」の ID のようなものを同じ Integer としてではなく、それぞれの型として分けて扱えるようになるので、単純なミスが減ると思います。ただの識別子として働く ID 値ならば演算もないとおもうので、型変換なども考えなくてよいと思いますし。