クラスとオブジェクト
クラスについてのおさらいが終わったところで、Scalaがサポートするさまざまなオブジェクト指向サポートについて解説します。
複数のコンストラクタ
クラスを定義する際に、クラスの宣言と同時にコンストラクタ引数を指定するのがScalaの構文です。では、コンストラクタが複数あるクラスを定義するには、どのようにするのでしょうか? 以下の定義をご覧ください。
import java.util.Date import java.net.URL // ブックマークを表すクラス。 // 基本コンストラクタは3つの引数をとる class Bookmark( val title:String, val url:URL, date:Date ) { // urlを文字列でとる補助コンストラクタ def this( title:String, url:String, date:Date ) = this( title, new URL( url ), date ) // urlを文字列でとり、dateを省略した補助コンストラクタ def this( title:String, url:String ) = this( title, new URL( url ), new Date ) }
このBookmarkクラスは、コンストラクタで3つの引数(title, url, date)をとるように定義されていますが、クラス内部に"def this( title:String, url:String, date:Date ) "のようにthisで定義されたメソッドを持っています。
このように、thisで定義されたメソッドは補助コンストラクタと呼ばれており、異なる引数をとるコンストラクタとして定義できます。クラス定義と同時に指定されているコンストラクタは基本コンストラクタと言います。
補助コンストラクタには、いくつかの制限があります。
- 補助コンストラクタは最初の処理で同じクラス内の、先に定義された他のコンストラクタを呼び出さなければならない
- 補助コンストラクタは、最終的に基本コンストラクタが呼び出されるようになっていなければならない
このように、Scalaでの複数のコンストラクタを定義する際の制限は、Javaより厳しくなっています。ただ、一般的にインスタンス化の方法が複数あるクラスを定義する場合は、補助コンストラクタよりこのあとに説明するコンパニオンオブジェクトにファクトリーメソッドを定義する場合が多いのです。
シングルトンオブジェクト
Scalaでは、objectキーワードによりシングルトンオブジェクトを定義できます。シングルトンオブジェクトとは、あるクラスのインスタンスがプログラムの中でただ一つしか存在しないオブジェクトです。Javaなどでシングルトンオブジェクトを定義する場合は、インスタンスが重複して生成されないように制御する必要がありますが、Scalaではclassキーワードのかわりにobjectキーワードを用いることでシングルトンオブジェクトを簡単に定義できます。
// ブックマークのデータを保持するシングルトンオブジェクト object MyBookmarks { // 内部でブックマークを保持するために変更可能なArrayBufferを利用する import scala.collection.mutable.ArrayBuffer // ブックマークを保持するArrayBuffer private val bookmarks = ArrayBuffer.empty[Bookmark] // ブックマークを追加 def add( bookmark:Bookmark ) = bookmarks += bookmark // ブックマークを表示 def show = bookmarks.foreach{ b => println( "%s : %s" format( b.title,b.url )) } }
リスト5の例は、MyBookmarksというシングルトンオブジェクトです。このオブジェクトはプログラム中で一つしかインスタンスが存在しません。代わりに、シングルトンオブジェクトはコンストラクタを定義できないようになっています。
objectキーワードで定義されたシングルトンオブジェクトは、通常のクラスと同様に内部にメンバーを持つことができます。MyBookmarksオブジェクトは、内部にprivateでブックマークのデータを持つprivateなbookmarksフィールドや、add/showなどのpublicメソッドを持っています。
scala> MyBookmarks.add( new Bookmark("今から始めるScala 前編" ,"http://codezine.jp/article/detail/5193/") ) res1: scala.collection.mutable.ArrayBuffer[Bookmark] = ArrayBuffer(Bookmark@feb5de5) scala> MyBookmarks.show 今から始めるScala 前編 : http://codezine.jp/article/detail/5193/
このように、インスタンス化せずにオブジェクト名を利用することでシングルトンオブジェクトにアクセスできます。
また、シングルトンオブジェクトは他のクラスを継承することが可能です。