Scala2.10の新機能を勉強する その4 ValueClass(続編)
前回は、ValueClassの使い方を勉強しました。
- メモリ割り当てが必要になる場合
- 制約
を次回はやります。と宣言したんですが、
今回は「メモリ割り当てが必要になる場合」のみに絞りたいと思います。
※制約の話はその5とかで、、、
メモリ割り当てが必要になる場合
Valueクラスは
オブジェクト割り当てを回避する
と書いてありましたが、
実は以下のような場合はインスタンス化が必要になります。
- 値クラスが別の型として扱われるとき。
- 値クラスが配列に代入されるとき。
- パターンマッチングなどにおいて、実行時の型検査を行うとき。
それぞれ試してみましょう。
値クラスが別の型として扱われるとき
「値クラスが別の型として扱われるとき」とはつまりどういうことでしょうか?
日本語ドキュメントを見ると、
汎用トレイトを拡張していて、
汎用トレイトの型として扱われるような場合の事のようです。
実際にコード書いて試してみます。
※メソッド名は適当なので、意味は気にしない
こんな感じで、
- 汎用トレイト(Hoge)として扱うメソッド「nameAsHoge」
- 値クラス(Foo)として扱うメソッド「nameAsFoo」
を定義してみました。
これをjadってみます。
… Predef$.MODULE$.println($outer.nameAsHoge(new Foo(1))); Predef$.MODULE$.println($outer.nameAsFoo(1)); …
大分はしょりましたが、「nameAsHoge」はnewされている(インスタンス化されている)ことがわかります。
値クラスが配列に代入されるとき
これは読んで字のごとくですが、
配列だけなのか??と思い、その他のコレクションも試してみました。
比較する為に、インスタンス化されない普通の代入パターンも書いてみました。※6行目
では、これもjadってみます。
… $outer.hoge_$eq("aaaa"); $outer.array_$eq((Hoge[])Array$.MODULE$.apply(Predef$.MODULE$.genericWrapArray(new Hoge[] { new Hoge("str") }), ClassTag$.MODULE$.apply(valueclass/memory/array/ValueClass_04$Hoge))); $outer.list_$eq(List$.MODULE$.apply(Predef$.MODULE$.genericWrapArray(new Hoge[] { new Hoge("str") }))); $outer.seq_$eq((Seq)Seq$.MODULE$.apply(Predef$.MODULE$.genericWrapArray(new Hoge[] { new Hoge("str") }))); $outer.set_$eq((Set)Predef$.MODULE$.Set().apply(Predef$.MODULE$.genericWrapArray(new Hoge[] { new Hoge("str") }))); $outer.map_$eq((Map)Predef$.MODULE$.Map().apply(Predef$.MODULE$.wrapRefArray((Object[])(new Tuple2[] { scala.Predef.ArrowAssoc..MODULE$.$minus$greater$extension(Predef$.MODULE$.any2ArrowAssoc(new Hoge("key")), new Hoge("value")) })))); …
最初の行以外は、すべて「new Hoge」されています。
パターンマッチングなどにおいて、実行時の型検査を行うとき
「パターンマッチングなどに」
など?など?!などってなんでしょうね、他に何があるんでしょう。。。
そういう所気になってしまうんですが、
とりあえず、「isInstanceOf」での型検査もやってみました。
比較する為に、型検査をしないパターンも最後に書いてます。
では、これもjadってみます。
… String s; String s1; String s2; s = "aaa"; if(new Hoge(s) == null) break MISSING_BLOCK_LABEL_122; String x = s; Predef$.MODULE$.println(x); BoxedUnit boxedunit = BoxedUnit.UNIT; $outer.hoge_$eq("bbb"); if(new Hoge($outer.hoge()) instanceof Hoge) Predef$.MODULE$.println($outer.hoge()); $outer.hoge2_$eq("ccc"); s2 = $outer.hoge(); s2; s2; s1 = "ccc"; JVM INSTR ifnonnull 102; goto _L1 _L2 _L1: break MISSING_BLOCK_LABEL_93; _L2: break MISSING_BLOCK_LABEL_102; JVM INSTR pop ; if(s1 != null) break MISSING_BLOCK_LABEL_118; break MISSING_BLOCK_LABEL_110; s1; equals(); JVM INSTR ifeq 118; goto _L3 _L4 _L3: break MISSING_BLOCK_LABEL_110; _L4: break MISSING_BLOCK_LABEL_118; Predef$.MODULE$.println("match"); …
ちょっと長くなってしまいましたが、「isInstanceOf」もインスタンス化されていますね。
型を検査する場合は、インスタンス化が必要です、ということでしょうか?
まとめ
今回は、メモリ割り当てが必要な場合、について勉強しました。
便利な機能を使う場合は、それがどのような事をしていて、
どういう時に最適化され、どういう時に最適化されないのか、
ということを知っておかないと、使う時気持ち悪いので、
こういう事知っておくのはとても大事な事だと思ってます。
※そんなに詳しく勉強したわけではないですが、、、
次回は、制約についてやりたいと思います。
これもとても大事そう。