クラス

クラス定義

Scala はオブジェクト指向プログラミング言語でもあるので、当然クラスの定義もできる。もっとも簡単な例は次のようになる。

scala> class Point(_x: Int, _y: Int) {
| val x = _x
| val y = _y
| }
defined class Point

これは x と y というフィールドを持つクラスだ。フィールドの宣言には val と var が使える。もちろん val で宣言したフィールドは代入できない。

クラスをインスタンス化するには new キーワードを使う。Point というクラス名の後につづく ( ) 内の引数がそのままコンストラクタの引数になる。

scala> val p = new Point(3, 2)
p: Point = Point@1409fe14

コンストラクタの引数名とフィールド名が同じでよければ、次のように簡単に書ける。

scala> class Point(val x: Int, val y: Int)
defined class Point

フィールドのアクセス制御

フィールドはデフォルトでパブリックなので、外側から参照することができる。

scala> p.x
res0: Int = 3

scala> p.y
res1: Int = 2

パブリックにしたくなければ、フィールドの宣言に private または protected キーワードをつける。private をつけるとそのクラスの中だけから、protected をつけるとクラスの派生クラスだけからアクセスできるようになる。private をつけた例を見てみよう。

scala> class Person(_name: String, _age: Int) {
| val name = _name
| private var age = _age
| }
<console>:13: warning: private var age in class Person is never used
private var age = _age
^

おっと、警告が出た。プライベートは変数 age が使われない、みたいなことを言われてるようだ。ま、そりゃそうだ。今はフィールドを操作するメソッドがないから、外からアクセスできないフィールドだけあっても役に立たないからな。でも、とりあえずクラス定義はできて、インスタンス化もできる。

scala> val andy = new Person("Andy", 27)
andy: Person = Person@4bd808d0

scala> andy.name
res0: String = Andy

scala> andy.age
<console>:13: error: variable age in class Person cannot be accessed in Person
andy.age
^

パブリックな name にはアクセスできて、プライベートな age にはアクセスできない様子がわかる。

型によるパターンマッチ

match 式では、値の型によるパターンマッチもできる。パターンには変数の後に : に続けて型を書く。こんなふうに。

scala> val obj: AnyRef = "String Literal"
obj: AnyRef = String Literal

scala> obj match {
| case v:java.lang.Integer =>
| println("Integer!")
| case v:String =>
| println(v)
| }
String Literal

AnyRef という型は、あらゆる参照型を代入できる型。よくわからないけどとりあえずそういうものだと思っておく。

で、この例では値の実体が文字列なので、初めの java.lang.Integer にはマッチせず、2番目の String にマッチしている。値は変数 v に束縛されるので後から使うことができる。

さて、ここで疑問なのは、どうして java.lang.Integer なんて型がいきなり出てきたかってこと。Int じゃダメなのか。試してみよう。

scala> obj match {
| case v:Int =>
| println("Int!")
| case v:String =>
| println(v)
| }
<console>:14: error: pattern type is incompatible with expected type;
found : Int
required: Object
case v:Int =>
^

ダメだった。なんかパターンの型の互換性がどうとか言ってる。Object を期待しているところに Int が来たと。

なんというか、まだ Scala の型システムについて理解してないんだけど、いきなり Java の型が出てくるのは気持ちが悪い。Scala の型だけで済ますことはできないんだろうか。