Scalaの勉強はじめました 3 〜オブジェクトとクラス①〜


はじめに

N予備校の「Scala基礎」コースを受講しています。
今回は、オブジェクトとクラスについてです。

クラス

複数のオブジェクトを作るための雛形のようなもの

class Cat(name: String) {
  def greet(): Unit = println(s"吾輩は${name}である")
}
val cat = new Cat("ねこ")
cat.greet()

nameがフィールド、greetがメソッド。

クラスの中でしか使わないメソッドやクラスの中だけでしかアクセスさせたくないフィールドには、privateというアクセス修飾子をつける。

抽象クラス

継承を使うことを前提に作られたクラスのこと。
インスタンス化はできない。abstractをつける。

abstract class Creature(var name: String) {
  def isAlive(): Boolean = true
}

class Human(_name: String) extends Creature(_name) 

オブジェクト

object MyApplication extends App {
  println("Hello!")
}

objectキーワードで宣言されるオブジェクトは、現JVMの実行環境でたった一つだけのMyApplication型のオブジェクト。

シングルトンオブジェクトという。

ファクトリメソッド

クラスのインスタンスを生成するメソッドのこと
Scala のオブジェクトの中で、 applyというメソッドを定義すると、そのメソッドは特別扱いされ、オブジェクト名(applyメソッドの引数) の形式で呼び出すことが可能となる

class Cat(private val name: String) {
  def greet(): Unit = println(s"吾輩は${name}である")
}
object Cat {
  def apply(name: String) = new Cat(name)
  def apply(id: Int) = new Dog(s"ねこID:${id}")
  def printName(cat: Cat): Unit = println(cat.name)
}

クラスと同名のオブジェクトを「コンパニオンオブジェクト」という。
同名クラスのプライベートメンバーにもアクセスできる。

val taro = new Cat("太郎")
Cat.printName(taro)

ケースクラス

class Point(val x: Int, val y: Int) {
  override def toString = s"Point($x, $y)"
}
object Point {
  def apply(x: Int, y: Int): Point = new Point(x, y)
}

これが、

case class CPoint(x: Int, y: Int)

となる。
メンバーフィールドの公開や、newの代わりとなるファクトリメソッドなどを自動的に用意してくれる。

sealed

Scalaで宣言されたファイルの中でしか利用できないクラス

パターンマッチの際に、継承されたクラスから漏れがあると警告を出してくれる。(コンパイル時に警告をイベントログに出力)
ケースクラスと併用して列挙型のように使う。

sealed abstract class Animal
case class Cat(name: String, age: Int) extends Animal
case class Dog(name: String, age: Int) extends Animal
case class Bird(name: String, age: Int) extends Animal

object Animal {
 def introduce(animal: Animal): String = {
    animal match {
      case Cat(name, age) => s"ねこのなまえは${name}、${age}さいです"
      case Dog(name, age) => s"いぬのなまえは${name}、${age}さいです"
      case Bird(name, age) => s"とりのなまえは${name}、${age}さいです"  
    }
  }
}

呼び出しは、

Animal.introduce(Dog("小次郎", 3))

まとめ

オブジェクト指向、雰囲気は大体わかるんですが、実際に抽象クラスだったりどう使い分けていくのか、頭の中がまだ整理できてません。
なんか実際に作らないとわからないかも。