Scala の型に関する知識
[履歴] [最終更新] (2016/02/13 18:02:36)

型の階層構造

object Main {
  def main(args: Array[String]): Unit = {
    // すべての型は 4 つに大別できます (Null型, Nothing型を除く)
    // Any <- AnyVal <- Unit,プリミティブ             <- Nothing
    // Any <- AnyRef <- String,その他のクラス <- Null <- Nothing
    val i: Int = 123 // プリミティブ型
    val void: Unit = () // Unit型 (値はある)
    val str: String = "string" // 文字列
    val obj: List[Int] = List(1,2,3) // その他のクラス (Option型なども含む)

    // すべての型は Any を継承
    println(i.isInstanceOf[Any]) //=> true
    println(void.isInstanceOf[Any]) //=> true
    println(str.isInstanceOf[Any]) //=> true
    println(obj.isInstanceOf[Any]) //=> true

    // すべての型は AnyRef または AnyVal のいずれかを継承 (AnyRef と AnyVal は Any を継承)
    def func1: AnyVal = i
    def func2: AnyVal = void
    def func3: AnyRef = str
    def func4: AnyRef = obj
    println(func1) //=> 123
    println(func2) //=> ()
    println(func3) //=> string
    println(func4) //=> List(1, 2, 3)

    // Null型はすべての AnyRef の子クラスを継承。インスタンスは null のみ。
    val myNull: Null = null
    // val i2: Int = myNull // エラー
    // val void: Unit = myNull // エラー
    val str2: String = myNull
    val obj2: List[Int] = myNull

    // Nothing型はすべての型を継承。インスタンス化できない。本当に値がない型です。
    def func5: Nothing = {
      throw new Exception
    }
  }
}

比較演算

AnyRef 型の比較は ==, !=, eq, ne です。AnyVal 型の比較は ==, != のみです。

object Main {
  def main(args: Array[String]): Unit = {
    // String 型は AnyRef 型を継承。Scala では以下は値の比較
    println("abc" == "abc") //=> true
    println("abc" != "ABC") //=> true

    // 他の AnyRef 型に関する例
    val obj1: List[Int] = List(1,2,3)
    val obj2: List[Int] = List(1,2,3)
    println(obj1 == obj2) //=> true (値は同じ)
    println(obj1 != obj2) //=> false
    println(obj1 eq obj2) //=> false (参照先は異なる; AnyRef に関しては eq が使用可能)
    println(obj1 ne obj2) //=> true

    // AnyVal 型に関しては eq/ne が存在しない
    val i1: Int = 1
    val i2: Int = 1
    println(i1 == i2) //=> true
    // println(i1 eq i2) // エラー: value eq is not a member of Int
  }
}
  • ==, != → 値を比較
    • Java における str1.equals(str2) 等の処理に相当 (Java には否定の比較はなし)
  • eq, ne → 同じ参照先であるかどうかを判定 (参照の比較)
    • Java における == および != に相当

暗黙の型変換 (implicit)

濫用するとコードが分かりにくくなることに注意して使用します。

object Main {
  def main(args: Array[String]): Unit = {

    // クラス定義
    class MyClassA {
      var prop: String = ""
      def methodA: Unit = {
        println("methodA")
      }
    }
    class MyClassB {
      var prop: Int = 0
      def methodB: Unit = {
        println("methodB")
      }
    }

    // 暗黙の型変換を定義
    import scala.language.implicitConversions // import が必要
    implicit def myConverterFromMyClassA2MyClass2(objA: MyClassA): MyClassB = {
      val objB = new MyClassB
      objB.prop = objA.prop.size
      objB
    }

    // myConverterFromMyClassA2MyClass2 が見えるスコープ内であれば変換される
    val objA = new MyClassA
    objA.prop = "string"
    val objB: MyClassB = objA
    println(objB.prop) //=> 6
    objA.methodA //=> methodA
    objA.methodB //=> methodB (暗黙の型変換のため実行できる)
  }
}

似たような型/インスタンスの区別

  • Nothing インスタンスを持てない、すべてのクラスのサブクラス
  • Unit 唯一のインスタンス () をもつクラス

インスタンス

  • null Null 型の唯一のインスタンス (シングルトン)
  • Nil 要素が空の List オブジェクト
  • None 無いことを表現する Option 型のインスタンス
関連ページ
    書式指定 object Main { def main(args: Array[String]): Unit = { println("%d + %d = %d".format(1, 1, 2)) //=> 1 + 1 = 2 } } 文字列の比較 『Scala の型に関する知識』をご参照ください。
    概要 Scala は JVM 上で動作するバイトコードにコンパイルできる言語です。JAVA よりも柔軟な記述ができます。事前にこちらからダウンロードおよびインストールしておいてください。基本的な文法をまとめます。 変数および定数 詳細は『Scala の型に関する知識』をご参照ください。 object HelloWorld { def main(args: Array[String]):
    相互変換 object Main { def main(args: Array[String]): Unit = { // 順序のあるコレクション // Traversable -> Iterable -> Seq // -> List // -> Array // -> Buffer -> ListBuffer, ArrayBuffer