連載
» 2012年10月04日 00時00分 公開

スケーラブルで関数型でオブジェクト指向なScala入門(11):カリー化、遅延評価などScalaの文法総まとめ&今後 (3/3)

[中村修太,クラスメソッド]
前のページへ 1|2|3       

DIをソースファイルだけで実現「自分型アノテーション」

 自分型アノテーションとは、自身のインスタンスを表すための「this」キーワードの別名のようなものです。基本コンストラクタの先頭で定義できます。名前は何を付けてもいいのですが、慣習的には「self」を使うことが多いようです。

class Sample {
    self =>
 
    val msg = "hello"
    def show =  { println("this.msg = " + this.msg);println("self.msg = " + self.msg) }
}
scala> new Sample().show
this.msg = hello
self.msg = hello

 当然、thisキーワードと自分で付けた別名は同じものを示します。これだけでは、あまり活用方法がありませんが、実は自分型アノテーションでは定義時に自身以外の別の型(クラス/トレイト)を指定可能です。

 こうすることで、そのクラス/トレイトを自身が継承していることと同じ扱いになります(複数のトレイトをミックスインしたい場合、「self: A with B with C =>」とします)。

 それでは、自分型アノテーションを使ってコンポーネント間の依存関係を定義してみましょう。まずはMyServiceトレイトを定義し、そのトレイトを実装するMyServiceImplトレイトを実装します。

trait MyService {
    def findAll():String
}
trait MyServiceImpl extends MyService {
    def findAll():String = "MyServiceImpl#findAll"
}

 次に、自分型アノテーションでMyServiceを指定したMyControllerクラスを定義します。

class MyController {
    self: MyService =>
 
    def execute = {
        println(findAll())
    }
}

 MyController内でMyServiceのメソッドを使えるのが分かります。では、MyControllerをインスタン化して使ってみましょう。MyServiceの実装がまだ決まっていないので、インスタン化の際にMyServiceImplを指定しています。

scala> val c = new MyController with MyServiceImpl
c: MyController with MyServiceImpl = $anon$1@69dfe453
 
scala> c.execute
MyServiceImpl#findAll

 MyControllerを実行すると、インスタン化時にミックスインしたMyServiceImplのfindAllメソッドが実行されています。ミックスインするクラスを変更すれば、簡単に実装を切り替えができます。

 このように、自分型アノテーションを使うことで、DI(依存性の注入)機能をソースファイルだけで実現できます。

 さらに、この手法だとコンパイル時にエラーが発見できるというメリットもあります。

 ただ、extendsして継承した場合は、「super」キーワードで継承したメソッドを呼び出せますが、自分型アノテーションでは呼び出せないので注意してください。

今後のScalaで導入が検討されている機能4選

 2012年8月現在、Scalaのバージョンは2.9.2がstableとなっており、次期バージョン2.10はMilestone 6となっています。ここでは、2.10で導入が検討されている機能をいくつか紹介します。

暗黙の型変換を用いたクラスの拡張が簡単になる「implicit Class」

 これは、暗黙の型変換をより直感的に記述する手法です。Scalaでは暗黙の型変換を使い、継承を用いずに型を拡張できます。

 まず、いままでの手法を見てみましょう。例として、Int型に暗黙の型変換を使ってshowメソッドを追加してみます。

//Intを拡張したクラス
class RichInt(self: Int) {
    def show(): Unit = println(self)
}
 
//IntからRichIntへ暗黙の型変換を行う
implicit def toRichInt(self: Int): RichInt = new RichInt(self)
scala> 100.show
100

 ここでは、以下の2ステップを踏んでおり、少々面倒です。

  • implicit defで暗黙の型変換を定義
  • 変換先クラスに追加したいメソッドを追加

 しかし、2.10から導入される予定のimplicit Classを使うことで、もう少し簡潔に記述できます。implicit Classを使うには、拡張した結果のクラスに「implicit」キーワード付与し、そのクラスのコンストラクタに、拡張元のクラスを指定します。

//Intを拡張したクラス(Scala 2.10を使う必要があります)
implicit class RichInt(self: Int) {
    def show(): Unit = println(self)
}
scala> 100.show
100

リフレクションAPI

 いままではJavaのリフレクションAPIを使うしかありませんでしたが、2.10からはScalaのリフレクションAPIが導入されます。

 このAPIを利用すると、Scala固有のリフレクション情報(implicitなど)を取得できます。リフレクションに関する情報は、こちらを参考にしてみてください。

マクロ

 2.10では、まだ実験的な導入ですが、この機能を用いるとコンパイル時に値が評価され、マクロを呼んでいる部分にインラインで展開されるようになります。

 すでに、いくつかのライブラリでは実用例もあるようです。マクロに関しては下記を参考にしてください。

AkkaのActorが標準のActorに

 前回の記事でも少し書きましたが、いままで使っていたScalaのアクターは非推奨になり、Akka(Java/Scala用並行処理ライブラリ)のアクターが導入されます。

 現状でも並行処理を記述する際はAkkaを使うことが多いと思いますが、2.10からはScala標準のアクターとして使えるようになります。

2.10は、もう試せる

 これ以外にもいくつか新しい機能が実装される予定です。2.10の正式リリースはもう少し先になるとは思いますが、公式サイトからダウンロードできるので、新機能に興味がある方は試してみてください。

Scalaは実用的な言語に

 さて、8カ月前から始まったこの連載も今回で最終回です。全11回にわたってScalaの基本を紹介してきましたが、いかがでしたか?

 連載第1回にScalaの紹介として、「オブジェクト指向、関数型言語の機能を統合することでより簡潔にコードの記述ができ、生産性が向上する」と言いました。いままでの連載を振り返ると、Scalaのいろいろな機能が“簡潔で分かりやすいコードを記述するため”にできていることが分かると思います。

 この数カ月でScalaを採用した実例はさらに増えました。国内でも事例が出てきていることから分かるように、すでにScalaは実用的な言語として認識されつつあります。

 Scalaは今後、まだまだ進化していく言語です。当然昔のバージョンのサポートはされていくとは思いますが、新しい機能の追加や変更もされていくでしょう。

 以前よりScalaの情報は入手しやすくなっており、日本語の書籍も何冊か出版されているので、最新の情報を追うことはそんなに難しくはないと思います。

 ここまで本連載をご覧いただき、ありがとうございました。この連載をきっかけに、Scalaに触れていただけたら幸いです。

中村修太

中村修太(なかむら しゅうた)

クラスメソッド勤務の新しもの好きプログラマです。昨年、東京から山口県に引っ越し、現在はノマドワーカーとして働いています。好きなJazzを聴きながらプログラミングするのが大好きです。


前のページへ 1|2|3       

Copyright © ITmedia, Inc. All Rights Reserved.

RSSについて

アイティメディアIDについて

メールマガジン登録

@ITのメールマガジンは、 もちろん、すべて無料です。ぜひメールマガジンをご購読ください。