Skip to content
Permalink
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
131 lines (102 sloc) 4.91 KB
layout title language discourse partof num next-page previous-page topics prerequisite-knowledge
tour
クラス
ja
true
scala-tour
4
traits
unified-types
classes
no-return-keyword, type-declaration-syntax, string-interpolation, procedures

Scalaにおけるクラスはオブジェクトを作るための設計図です。 クラスはメソッド、値、変数、型、オブジェクト、トレイト、クラスを持ち、それらはまとめて メンバー と呼ばれます。 型、オブジェクト、トレイトはツアーで後ほど取り扱います。

クラスを定義する

最小のクラス定義は単純にキーワードclassと識別子だけというものです。 クラス名は大文字から始まるべきです。

class User

val user1 = new User

newキーワードはクラスのインスタンスを作るために使われます。 Userはコンストラクターが定義されていないので、引数なしのデフォルトコンストラクターを持ちます。 しかしながら、コンストラクターとクラス本体は頻繁に欲しくなるでしょう。 こちらは位置情報のクラス定義の例になります。

class Point(var x: Int, var y: Int) {

  def move(dx: Int, dy: Int): Unit = {
    x = x + dx
    y = y + dy
  }

  override def toString: String =
    s"($x, $y)"
}

val point1 = new Point(2, 3)
point1.x  // 2
println(point1)  // prints (2, 3)

このPointクラスは4つのメンバーを持ちます。 変数xy そしてメソッド movetoStringです。 多くの他の言語とは異なり、プライマリコンストラクタはクラスのシグネチャ(var x: Int, var y: Int)です。 move メソッドは2つの整数の引数を受け取り、情報を持たない Unit 値 () を返します。 これは大雑把に言えば、Javaのような言語におけるvoidに対応します。 その一方でtoStringは引数を受け取りませんが、Stringの値を返します。 toStringAnyReftoStringをオーバーライドしているので、overrideキーワードのタグが付いています。

コンストラクター

コンストラクターは次のようにデフォルト値を与えると省略可能なパラメーターを持つことができます。

class Point(var x: Int = 0, var y: Int = 0)

val origin = new Point  // x と y には共に0がセットされます。
val point1 = new Point(1)
println(point1.x)  // 1 が出力されます。

このバージョンのPointクラスでは、xy はデフォルト値0を持ち、引数が必須ではありません。 しかしながらコンストラクタは引数を左から右に読み込むため、もしyの値だけを渡したい場合は、パラメーターに名前をつける必要があります。

class Point(var x: Int = 0, var y: Int = 0)
val point2 = new Point(y=2)
println(point2.y)  // 2 が出力されます。

これは明快さを高めるための良い習慣でもあります。

プライベートメンバーとゲッター/セッター構文

メンバーはデフォルトではパブリックになります。 クラスの外から隠したい場合はprivateアクセス修飾詞を使いましょう。

class Point {
  private var _x = 0
  private var _y = 0
  private val bound = 100

  def x = _x
  def x_= (newValue: Int): Unit = {
    if (newValue < bound) _x = newValue else printWarning
  }

  def y = _y
  def y_= (newValue: Int): Unit = {
    if (newValue < bound) _y = newValue else printWarning
  }

  private def printWarning = println("WARNING: Out of bounds")
}

val point1 = new Point
point1.x = 99
point1.y = 101 // 警告が出力されます。

このバージョンのPointクラスでは、データはプライベート変数 _x_y に保存されます。 プライベートなデータにアクセスするためのメソッドdef xdef y があります。 def x_=def y_=_x_y の値を検証し設定するためのものになります。 セッターのための特別な構文に注意してください。 セッターメソッドはゲッターメソッドの識別子に_=を追加し、その後ろにパラメーターを取ります。

プライマリコンストラクタのvalvar を持つパラメーターはパブリックになります。 しかしながらval は不変となるため、以下のように記述することはできません。

class Point(val x: Int, val y: Int)
val point = new Point(1, 2)
point.x = 3  // <-- コンパイルされません。

valvar が存在しないパラメーターはクラス内でだけで参照できるプライベートな値や変数となります。

class Point(x: Int, y: Int)
val point = new Point(1, 2)
point.x  // <-- コンパイルされません。
You can’t perform that action at this time.