やっぱり java の generic にムキムキしちゃうの - Genericな関数の型指定で死亡
class A<T> { static public interface IHashGetter<T> { public int getHash(T t); }; public A() { this(getDefaultHashGetter()); // ※↑コンストラクター A<T>(A.IHashGetter<Object>) は未定義です。 } public A(IHashGetter<T> getter) { // こっちが本線 } static <U> IHashGetter<U> getDefaultHashGetter() { return new IHashGetter<U>() { public int getHash(U t) { return t.hashCode(); } }; } };
こんなクラスがあったとします。(処理の内容はともかく:ぉ)
class A のコンストラクタでは "IHashGetter" を要求しますが、用意するときが面倒な時は指定無しにすると、内部で用意したデフォルトの getter を利用する…という感じです。
ただ、上記のコードではデフォルトコンストラクタでエラーが出ちゃいます。うん確かにそりゃそうだよね。U に型指定出来てないもんね……ってことで、型指定(T を渡したい)をするわけですが…ここで躓きました。
C++屋 のノリで指定してみるかしら!
public A() { this(getDefaultHashGetter<T>()); // ※↑ // トークン "(" に構文エラーがあります。 // このトークンの後には Expression を指定する必要があります。 }
oh...
そういえば、Javaは型指定を関数の前に付けるんだっけか…
java屋さんのノリで指定してみるかしら!
public A() { this(<T>getDefaultHashGetter()); // ※↑ // トークン "<" に構文エラーがあります。 // このトークンを削除してください。 }
……どうしろと。
悩んだあげく、私はひらめきピッカリン! ダミーの引数をあたえて自動的に型推論作戦 かしら!
型推論してみるかしら! - その1
public A() { this(getDefaultHashGetter(new T())); // ※↑ // 型 T のインスタンスを生成できません。 } static <U> IHashGetter<U> getDefaultHashGetter(U dummy) { return new IHashGetter<U>() { public int getHash(U t) { return t.hashCode(); } }; }
generic で指定した型は new 出来ないんだった…。 ってか、そもそも勝手に new するのも場合によっちゃ危険かもしれんしなぁ。
ほいじゃぁ、インスタンスは作らないけど、nullで初期化した変数だけ用意して「型」だけ引っ張って来ちゃるかしら…ッ!
型推論してみるかしら! - その2
public A() { T t = null; this(getDefaultHashGetter(t)); // ※↑ // コンストラクター呼び出しは、 // コンストラクター内の最初のステートメントである必要があります。 } static <U> IHashGetter<U> getDefaultHashGetter(U dummy) { return new IHashGetter<U>() { public int getHash(U t) { return t.hashCode(); } }; }
むおおおおおおおおお!!! orz
そうだよなぁ…。 this() とか super() の前に、ステートメントがあると駄目なんだった…
……ってか、えぇえええ!? んじゃぁそうすりゃえぇってのよ……! おしえて!はてなよ○せいさんッ!
悩んだ果てに...
public A() { this(A.<T>getDefaultHashGetter()); // OK } static <U> IHashGetter<U> getDefaultHashGetter() { return new IHashGetter<U>() { public int getHash(U t) { return t.hashCode(); } }; }
A. で名前解決しなきゃ行けないとかマジ何それ
class A のコンストラクタの中におるのに、更に A. が必要とかさーもー。ああああ orz