Scalaの基礎まとめ その2
この記事はhttp://befool.co.jp/blog/chainzhang/basic-of-scala-1/の引き続きです。
クラス
ScalaはOOPによく使うclass
というコンセプトもしっかりサポートしています。Scalaのクラスにはcase class
とclass
二種類ある。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のObjact
はSingleton
の作成、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
クラスにEvaCounterTrait
をextends
します:
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が面白そう」と思ってもらえれば嬉しいです。