minimize

事業拡大のため、新しい仲間を募集しています。
→詳しくはこちら

クラス定義

Scala では、クラスコンストラクタの引数をソース先頭で定義する。

class Rational(n:Int, d:Int) { ... }

こうすることによって、Scala は以下の処理を行う。

つまり、こういうことだ。

class Rational {
  private int n;
  private int d;
  
  public Rational(int n, int d) {
    this.n = n;
    this.d = d;
  }
}

たった一行で、これだけのコードが自動生成される。
これを活用すれば、Scala では(あの長ったらしい)代入コードを書く必要が無い。

class Rational(val n:Int, val d:Int)
class Rational(var n:Int, var d:Int)

さらに上記のように val や var キーワードを付けることによって、
Scala はこれらの Getter / Setter を自動生成する。
val は読み込み専用フィールドの意味で、Getter のみ生成する。
var は書き込み可能なフィールドの意味で、Getter および Setter を生成する。

外部からの Getter が必要無ければキーワード無で、
必要ならば val 付で、さらに Setter も必要ならば var 付で宣言しよう。

Scala は Immutable なクラスを好む。Mutable なクラスは必要最小限にするのが、Scala の流儀。
一つでも var を付ければ、そのクラスは Mutable になってしまう。

複数のコンストラクタ

上記のように、Scala ではクラスにデフォルトのコンストラクタを用意するのが一般的。
いくつかの引数をデフォルト値で呼び出す場合などは、以下のようにクラス内コンストラクタを定義する。

class Rational(n:Int, d:Int)
{
  def this(d:Int) = { this(0, d) }
}

Java の記述法とは異なるので注意。

継承、実装

クラスの継承は Java と同じく extends を使う。
Scala の trait を実装するには、with を使う。

class Teacher extends Person with Speakable, Runnable

親クラスのコンストラクタ呼び出しは以下のようにする。

class Student(firstName:String, lastName:String, age:Int, val subject:String)
  extends Person(firstName, lastName, age)

注意するのは、Student 側の firstName, lastName, age の3変数には val などのキーワードを付けないこと。
これらは Person で val 定義されている。
Student 側で val 定義すると、Scala はその Getter を生成しようとするが
これが Person とぶつかりコンパイルエラーとなってしまう。

trait

Scala は interface の代わりに trait を使う。
trait は abstract class であり、実装も含めることができる。
ただし、コンストラクタには引数を取ることができない。

trait は派生させて別の trait を作ることができる。

trait RichIterator[T] extends AbsIterator[T] { ... }

class には trait を extends することも with することもできる。

class StringIterator(s: String) extends AbsIterator[Char]
class Iter(args: String) extends StringIterator(args) with RichIterator[Char]

ただし、extends できるのは一つのみ。

また、trait は abstract class であるから直接 new することも可能。

new Set[T] {
  def include(x: T): Set[T] = xs prepend x
  def contains(x: T): boolean = !isEmpty && (xs.head == x || (xs.tail contains x))
}