Scalaの基礎まとめ その2

ChainZ(クリエイター)
いろいろやってます。

この記事はhttp://befool.co.jp/blog/chainzhang/basic-of-scala-1/の引き続きです。

クラス

ScalaはOOPによく使うclassというコンセプトもしっかりサポートしています。Scalaのクラスにはcase classclass二種類ある。case classは関数型プログラミングに特化したクラスであって、全てのメンバー変数がvalタイプになる。

class People(var name: String, val age: Int)
case class Animal(name: String, age: Int)
val p = new People("Hoge", 21)
p.name = "Mori"
println(p.name) // "Mori"
val a = new Animal("cat", 3)
a.name = "dog" // ERROR!

Class

Scalaのclassの定義は関数と少し似ています、しかし、引数がそのままclassのプロパティー(メンバー変数)になります。なお、scalaはプロパティーのタイプによって、自動的にgetterとsetterを作成します。

タイプ 権限
var GetterとSetter両方作成します
val Getterのみ作成します
private var GetterとSetter作成しません、class内アクセスのみ
private val GetterとSetter作成しません、class内アクセスのみ
<空> case classの場合はprivate valになる, classの場合はprivate varになる
class Player(var name: String, var score: Int = 0) {
override def toString : String = s"$name : $score"
}
object NonePlayer extends Player(score = 0, name = "")
// objectはsingletonです、最初のアクセスのみで初期化します。
class Eva(
val name: String,
var power: Int = 0,
private var _pilot: Player = NonePlayer)
// pilotのsetterとgetterをカスタマイズするので、privateにします
{
// pilot getter
def pilot: Player = _pilot
// pilot setter
def pilot_=(p: Player): Unit = {
power = p.score
_pilot = p
}
override def toString = _pilot match {
case NonePlayer => s"[無人]$name(power: $power)"
case _ => s"$name(power: $power, pilot: ${_pilot.name})"
}
// matchはScalaでよく使うメソードです、他の言語だとswitchのようなものだが、switchよりパワフルです。
}
val e = new Eva("初号機")
println(e) // [無人]初号機(power: 0)
e.pilot = new Player(name = "Shinji", score = 9000)
println(e) // 初号機(power: 9000, pilot: Shinji)

この例では、すべて戻り値のタイプを指定していますが、Scalaは十分スマートなので、戻り値のタイプは普通に書かなくても大丈夫です。もちろん、書いたほうがより良いプログラミング習慣を身につけるでしょう。

Object と trait

ScalaのObjactSingletonの作成、classと組んでCompinion Objectを作るとかに使います。traitはScalaでJavaのInterfaceのような役割をしています。JavaのInterfaceよりできること多いです。メソードを既存のclassにインジェクトしたりすることもできる。

// Compinion Object
// Evaクラスのstaticメソードなどは、object Evaの中で定義する
// (Scalaにはstaticというキーワードがないので、staticメソードはclassの中で直接定義できません。)
object Eva {
var count = 0
def status = s"Evaが${count}台作成されています"
}
trait EvaCounterTrait {
Eva.count += 1
// increase counter
}

既存のEvaクラスにEvaCounterTraitextendsします:

class Eva(
val name: String,
var power: Int = 0,
private var _pilot: Player = NonePlayer
) extends EvaCounterTrait

すると、newで作成されたEvaの数がEva.statusで見れるようになります。

まとめ

Scalaを勉強して2週間ぐらい経って、文法に慣れつつあるものの、Funcation Programming(関数型プログラミング)の思考などに結構難航しています。FPをやると少し高度な数学知識(大学レベル)が必要だなと実感しています。でもScalaは少ないコードで安定したアプリを作れるというとこが魅力で、これからも長く付き合おうと思っています。

ちなみに、この記事は初心者向けて書いています。細かいところは省略しています。もし「Scalaが面白そう」と思ってもらえれば嬉しいです。