2013年12月28日土曜日

C#とJava

久々の更新。

最近、お仕事でJavaを触ってます。
C#をこよなく愛する私としてはJavaも嫌いではないんだけど、やはり「C#だと簡単に出来るのに…」的なことがしょっちゅう登場します。
まあ、私がJavaを知らないだけで、Javaの人も同じようなことを思っているんだと思うんですけどね。


1. ラムダ式
例えば、Collection<T>のremoveAllメソッドとかを見てみます。
Javaだとこいつの引数はCollection<?>型になっていて、「引数のコレクションに含まれているものをこのコレクションから全部除きます」とかって機能になってます。

例えば「メニューリストから嫌いな食べ物を除く」とかであれば、
List<string> menuList = getMenuList(); //メニューを取得

List<string> hateList = new ArrayList<string>(); //嫌いなものを定義
list.add("なす");
list.add("きゅうり");
list.add("ピーマン");

menuList.removeAll(list); //嫌いなものをメニューから除外
こんな感じで使うのかな?

これならいいんですが、例えば「3以上の数を除く」とかになると、
List<int> numberList = getNumberList();
List<int> removeList = new ArrayList<int>();
list.add(4);
list.add(5);
list.add(6);
//...
いやいや無理だコレ。
まあ、ループで書けば実装自体は簡単に出来ると思いますけどね。

対してC#の場合は、removeAllの引数がpredicateになってます。
要は、匿名メソッドを渡すことでその条件で除外できるってこと。
さらにC#はラムダ式がサポートされているので…
List numberList = GetNumberList();
numberList.RemoveAll(e => e >= 3);
って書けます。楽ちんすぎるコレ。
Java8ではラムダ式がサポートされるという話なので、これはほんとに期待です。


2. 拡張メソッド

上記の例でいえば、Javaにも匿名メソッドがあるので、匿名メソッドを引数に持つ共通関数を作成すれば似たようなことが実現可能だと思います。
しかし、C#の場合には拡張メソッドという強力な機能があります。

例えば、「文字列から『た』だけ抜く機能」を作成したい場合、Javaだと
public class TanukiUtil {
 public static String removeTa(String param){
  return param.replace("た", "");
 }
}

String tanuki = TanukiUtil.removeTa("あいうたえおかきたたくけこ");
という感じに書くことになると思います。
しかしC#の場合、この機能をString型自体に持たせることができるわけじゃないっすか。
public static String RemoveTa(this string param)
{
    return param.Replace("た", "");
}

String tanuki = "あいうたえおかきたたくけこ".RemoveTa();
みたいな感じで。
だから例えば「この言語のこのクラスのこの機能欲しいな~」とか思ったら、そのクラスの拡張メソッドで似たようなものを作ってしまえばいいわけです。
ぶっちゃけ「なんとかUtil」みたいなクラスなんてもう要らない。
この機能さえあれば、JavaでLinqToObjectを実装することだって不可能じゃなかったはず。

そんなわけで、やっぱりC#が好きな雨凪でした。
もう戻れないかもしれない。

(追記)
nullが絡む場合は拡張メソッドだめですね。
「IsNullOrDefaultValue」みたいなメソッドを拡張メソッドで実装することはできないので、結局はなんとかUtilが必要になってしまうのだ。

0 件のコメント:

コメントを投稿