LoginSignup
2

More than 5 years have passed since last update.

Scalaにおける値型(列挙型、Beans)の表現

Last updated at Posted at 2016-10-15

Scala Design Patternsを読んでいたところ、Scalaにおける値型(列挙型, Beans)の自然な表現が紹介されていたので、まとめました。

値型とは?

値型とは、メソッドを持たず、値のみを保持するオブジェクトのことです。
ここでは値型として、列挙型とBeansを紹介します。

列挙型

定義の方法

sealed abstract trait Weekday

case object Sunday extends Weekday
case object Monday extends Weekday
case object Tuesday extends Weekday
case object Wednesday extends Weekday
case object Thursday extends Weekday
case object Friday extends Weekday
case object Saturday extends Weekday

ポイント

  • 列挙型の本体(Weekday)を、sealedキーワードで修飾する。
    • こうすることで、誰かが勝手にWeekdayを拡張して8つ目の曜日を作るすることができない。
    • パターンマッチに漏れがあると、コンパイラが警告してくれる
  • 本体をインスタンス化できないよう、abstract修飾子を施す
  • 具体的な値はcase objectとして定義し、本体(Weekday)を継承する
    • caseキーワードを付与することで、パターンマッチが可能になる
    • インスタンスを区別する必要がまったくないため、classではなくobjectで定義する

使い方

def weekdayToNum(weekday: Weekday): Int = 
    weekday match {
        case Sunday => 0
        case Monday => 1
        case Tuesday => 2
        case Wednesday => 3
        case Thursday => 4
        case Friday => 5
        case Saturday => 6
    }

val monday: weekDay = Monday

weekdayToNum(monday) // => 1

Beans

Beansは、プロパティとその読み書き機能のみを持つオブジェクトです(厳密な意味でのJavaBeansにはもう少し色々制約がありますが、ここではデータ型としての機能だけに着目します)。

定義の方法

sealed case class Name(firstName: String, lastName: String)

ポイント

  • sealedを使用して勝手に拡張されないようにする
  • case classとして定義し、パターンマッチを可能にする
  • 必要なメンバ変数をコンストラクタに定義するだけ。クラスの本体を書く必要なし。

使用法

val bob = Name("Bob", "Dylan")
bob.lastName // => Dylan

代数的データ型(ADT)

上で紹介したような値型のことを、関数型プログラミングでは代数的データ型(ADT = Algebraic Data Types)といいます。
そのうち、列挙型の表現として紹介したものをSUM ADT、Beansの表現として紹介したものをPRODUCT ADTと言います。

SUM ADTとPRODUCT ADTの複合型

SUM ADTとPRODUCT ADTを合体させることも可能です。
次は図形を表すADTです。

sealed abstract trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape

def calcArea(shape: Shape): Double =
    shape match{
        case Circle(r) => r * r * 3.14
        case Rectangle(w, h) => w * h
    }

val c = new Circle(1)
calcArea(c) // => 3.14

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2