Java での型変数とか

Mixi の「Java の課題丸投げ」コミュで,「オブジェクト指向」トピって立ってて,
回答者は真面目に応えていたけど,それはそれで面白くなかったので,
自分でも書いてみた.

内容はこんな感じ,適宜編集してある.

課題1

ラーメンをオブジェクト指向で表現。
3種類程度のラーメンが表現できるようにする。
- フィールド     ... (1)
- メソッド       ... (2)
- オーバーロード ... (3)
- オーバーライド ... (4)
- カプセル化(他クラスからのアクセスはgetメソッドとsetメソッドのみ) ... (5)
が確実に表現されていること。

実行は以下のクラスから呼び出される
  class RamenExample{
      public static void main(String [] args){
          Ramen shouyuRamen = new Ramen("しょうゆ");
          Ramen misoRamen = new Ramen("みそ");
          Ramen shioRamen = new Ramen("しお");
      }
  }

また、以下のクラスは生成が条件
  class Ramen {  }
  class Utsuwa {  }
  class Soup {  }
  class Pasta {  }
  class Topping {  }

結果としては,うん.まぁ.あんまり面白く書けなかった.
とあいえ,Java の型変数の書き方がわかったので良しとしよう.

import java.util.ArrayList;
import java.util.LinkedList;

// 条件のクラス

class Ramen {

    // メソッド(Ramen, toString, ...)
    Ramen(String type) {
        utsuwa = new Utsuwa();
        pasta = new Pasta();
        topping.add(new Topping(Topping.Type.チャーシュー));
        topping.add(new Topping(Topping.Type.卵));
        topping.add(new Topping(Topping.Type.ネギ));

        try {
            soup = new Soup(type);
        } catch (IllegalArgumentException e) {
            // 存在しないラーメンを頼まれたら,デフォルトにしちゃうよ
            soup = new Soup();
        }

        System.out.println(this);
    }

    public String toString() {
        LinkedList<Topping> list = new LinkedList<Topping>(topping);
        return
              "器:         " + utsuwa + "\n"
            + "スープ:     " + soup + "\n"
            + "麺:         " + pasta + "\n"
            + "トッピング: " + CollectionUtil.join(list, ", ");
    }

    // フィールド(utsuwa, soup, pasta, topping)
    Utsuwa utsuwa;
    Soup soup;
    Pasta pasta;
    ArrayList<Topping> topping = new ArrayList<Topping>();
}

class Utsuwa {
    enum Type {
        ラーメンどんぶり
    }
    Utsuwa() {
        this.type = Type.ラーメンどんぶり;
    }
    public String toString() {
        return type.name();
    }
    Type type;
}

class Soup {
    enum Type {
        しょうゆ, 
            みそ,
            しお
            }

    // オーバーロード(Soup)
    Soup() {
        this(Type.しょうゆ);
    }
    Soup(String type) throws IllegalArgumentException {
        this(Type.valueOf(type));
    }
    Soup(Type type) {
        this.type = type;
    }

    public String toString() {
        return type.name();
    }
    Type type;
}

class Pasta {
    enum Type {
        中太麺
    }
    Pasta() {
        this.type = Type.中太麺;
    }
    public String toString() {
        return type.name();
    }
    Type type;
}

class Topping {
    enum Type {
        チャーシュー,
            卵,
            ネギ,
    }
    Topping(Type type) {
        this.type = type;
    }
    public String toString() {
        return type.name();
    }
    Type type;
}

// ここから補助クラス,インターフェイス

class CollectionUtil {

    public static <T> String join(LinkedList<T> list, final String delim) {
        String first = list.removeFirst() + "";
        return foldLeft(list, first, new Procedure<T, String>() {
                // オーバーライド(apply)
                @Override
                public String apply(String init, T element) {
                    return init + delim + element;
                }
            });
    }

    public static <A, B> B foldLeft(LinkedList<A> list, B init, Procedure<A, B> proc) {
        if (list.size() == 0) {
            return init;
        } else {
            B next = proc.apply(init, list.removeFirst());
            return foldLeft(list, next, proc);
        }
    }
}
interface Procedure<A, B> {
    public B apply(B init, A element);
}

ソース全部