5 クラス

前に見たように、Scala はオブジェクト指向言語であり、それゆえにクラス*2の概念があります。Scala のクラスは、Java の構文と似た構文で宣言します。重要な違いは Scala のクラスはパラメータを持てるということです。以下の複素数の定義で示します。

class Complex(real: Double, imaginary: Double) { def re() = real def im() = imaginary }

この複素数クラスは2つの引数、複素数の実部と虚部を取ります。これらの引数は Complex クラスのインスタンスを生成する時に、 new Complex(1.5, 2.3) のように渡されます。このクラスは2つのメソッド、re と im を持ち、実部と虚部へのアクセスを与えます。

これら2つのメソッドの戻り値型が明示的に与えられていないことに留意すべきです。コンパイラが自動的に推論し、メソッドの右辺を見て、両者の戻り値型が Double であることを演繹します。

コンパイラはこの場合のようにいつも型を推論できるとは限りませんし、不運にも、どんな場合に推論できるかできないかを知る簡単な規則はありません。実際には、通常これは問題にはなりません。なぜなら明示的に与えられていない型を推論できない時は、コンパイラが苦情を言うからです。簡単な規則としては、Scala の初心者プログラマは、型を文脈から簡単に演繹できると思った時は型宣言を省略して、コンパイラが同意するか試すべきでしょう。しばらくするとプログラマは、どんな時に型を省略しどんな時に明示的に指定すべきかについて、勘が働くようになるでしょう。

5.1 引数無しのメソッド

メソッド re と im のちょっとした問題は、下記の例のように、呼び出すために名前の後に空の括弧の組を付けなくてはならないことです。

object ComplexNumbers { def main(args: Array[String]) { val c = new Complex(1.2, 3.4) println("imaginary part: " + c.im()) } }

もし実部と虚部にあたかもフィールドのように、空の括弧の組なしでアクセスできたらよいでしょう。Scala ではこれは 引数無し メソッドとして定義することで可能です。そのようなメソッドは、引数が0個のメソッドと異なり、宣言時でも使用時でも名前の後ろに括弧を必要としません。わたしたちの Complex クラスは次のように書き換えられます。

class Complex(real: Double, imaginary: Double) { def re = real def im = imaginary }

5.2 継承とオーバーライド

全ての Scala クラスはスーパークラスを継承しています。スーパークラスが指定されていない時、例えば前節の Complex クラスの例では、scala.Object が暗黙的に使用されます。

Scala ではスーパークラスから継承したメソッドをオーバーライドできます。しかし、不用意にオーバーライドされることを避けるために、メソッドをオーバーライドする際には override 修飾子が必須です。例では、Complex クラスは Object から継承した toString メソッドを再定義して拡張しています。

class Complex(real: Double, imaginary: Double) { def re = real def im = imaginary override def toString() = "" + re + (if (im < 0) "-" else "+") + im + "i" }

*2 補足しておくと、いくつかのオブジェクト指向言語はクラスの概念を持っていないことに注意すべきですが、Scalaはそういったものの1つではありません。