takaha.siの技術メモスマートフォン用の表示で見るtakaha.siの技術メモ勉強したことをお伝えします。誰かの役に立てればいいな...この広告は、90日以上更新していないブログに表示しています。踏んだのでメモScalaにはtraitという機能があります。traitは「それ単体で動作することはなく、他classを拡張(mixin)するか、他classから継承されることによって動作するエンティティ」と定義して良いと思います。JavaのInterfaceにたとえられることもありますけども、JavaのInterfaceが実装を持つことができないのにたいして、Scalaのtraitは実装を持つことができます。Scalaのtraitは便利で、mixinしてclassに機能をどんどん追加していくという事ができます。実質、多重継承のようなこと事ができてしまいます。この機能、利便性と引き換えに危険性が伴います。乱用すると複雑な継承関係を容易に生み出してしまい、コードの可読性が低下します。最悪NullPointerException(ヌルポ)でプログラムが死にます。ScalaはOptionさえ適切に使ってればヌルポは根絶できるのだと無邪気に考えていた私は甘かったです。BaseFunc1をmixinしています。実行すると、NullPointerExceptionが起こります。Main.main(bbbb.scala)まあちょっと考えれば、このコードがなぜヌルポが引き起こすのかはすぐわかると思います。rpc(14行目)がまだ決定されておらず、RPCBinderにnullが放り込まれてnewされちゃうんですね。BaseDefaultの方でインプリ(19行目)されており、BaseModel1でmixinされてしまっている(31行目)ので、コンパイルは通ってしまうわけです。そもそもこんな意味不明なコードを書くんじゃない!というのはもちろんそのとおりです。脳死プログラミングしているときでさえこんなコードには絶対ならない!と断言はできないと思いますし、なまじコンパイルが通ってしまうのでエラーは実行時に当該のパスを踏むまで見抜けません。ちなみに私はリファクタリングをしているときにこれに陥りました。いうわけで、scalaのtraitは注意して使わないといけないなと思いました。mixinがされているコードをレビューするときは、こういうエラーを引き起こす潜在因子がないかどうかちょっと考えてみるべきかもしれません。Baseを以下のように変更すれば問題なく実行されます。RPCBinder(rpc)}RPCbinderをnewするときにlazyをつければ、意図したとおり、ヌルポはでずに動きます。動くには動きますが、コードとして明示的に記述されない初期化の順番というものを、コードを読む人に意識させてしまうという点でこのコードが良くないということに変わりはないと思います。いうコードを書くべきではない。陥らないように注意すべきであるというそもそも論に変わりはないでしょう。p.s.lazyは、Scalaに対して初期化のコードの実行順番の変更を行うものでありますが、使い方によってはもっとヤバイ自体に陥ります。それはデッドロックです。以下に例が上げられています。gist.github.comヌルポはまだ可愛い方で、プログラムが落ちてくれるのでわかりやすいですよね。最新記事scalaのtraitの危険性10GbE時代に向けたNAS環境を構築する月別アーカイブはてなブログをはじめよう!tkh86さんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。