「Scalaスケーラブルプログラミング」で気になったところまとめ ~ 4章&5章 ~
この記事は?
- 作者: Martin Odersky,Lex Spoon,Bill Venners,羽生田栄一,水島宏太,長尾高弘
- 出版社/メーカー: インプレス
- 発売日: 2016/09/20
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
第4章 クラスとオブジェクト
クラス定義は基本的にJavaと同じ
Scalaでは以下のようにクラスを定義する
class ChecksumAccumulator { // ここにクラス定義を書く }
オブジェクトを作成するときはnew
を使う
val ca = new ChecksumAccumulator
val
で作成したオブジェクトに別のオブジェクトを代入することはできない
scala> val hoge = List("hoge","fuga") hoge: List[String] = List(hoge, fuga) scala> hoge = List("foo", "bar") <console>:8: error: reassignment to val hoge = List("foo", "bar") ^
Scalaでは明示的にアクセス修飾子を指定しなければメンバーはpublic
になる
アクセス修飾子をprivate
にした場合
// 例で使用するクラス class ChecksumAccumulator { private var sum = 0 }
scala> val ca = new ChecksumAccumulator ca: ChecksumAccumulator = ChecksumAccumulator@60dd0587 scala> ca.sum = 5 // privateなのでアクセスできない <console>:12: error: variable sum in class ChecksumAccumulator cannot be accessed in ChecksumAccumulator ca.sum = 5 ^ <console>:13: error: variable sum in class ChecksumAccumulator cannot be accessed in ChecksumAccumulator val $ires0 = ca.sum ^
アクセス修飾子を指定しなかった場合
// 例で使用するクラス class ChecksumAccumulator { var sum = 0 }
scala> val ca = new ChecksumAccumulator ca: ChecksumAccumulator = ChecksumAccumulator@60dd0587 scala> ca.sum = 5 // アクセス修飾子を指定していない(public)なのでアクセス可能 ca.sum: Int = 5
メソッドのパラメータはval
である
パラメータがval
なのは、val
の方が推論に便利だかららしい。(p.081)
// 例 class ChecksumAccumulator { private var sum = 0 def add(b: Byte): Unit = { b = 1 // bはvalなので代入できない。コンパイルエラーになる。 sum += b } }
Scalaにはシングルトンオブジェクトと呼ばれるものがある
Scalaではクラスが静的メンバー(static member)を持つことができない。その代わりにシングルトンオブジェクトと呼ばれるものを持つことができる。
シングルトンオブジェクトはclass
キーワードの代わりにobject
キーワードを使う。
object ChecksumAccumulator { // ここに定義を書く }
クラスとシングルトンオブジェクトが同じ名前を持つ時、そのクラスのコンパニオンオブジェクトと呼ぶ。
逆にクラスはそのオブジェクトのコンパニオンクラスと呼ぶ。
ちなみにコンパニオンクラスと同じ名前ではないシングルトンオブジェクトをスタンドアロンオブジェクトと呼ぶ。
クラスとそのコンパニオンオブジェクトはお互いのprivateメンバーにアクセスできる
class Hoge { private val name = "hoge" } object Hoge { def printHogeName(): Unit = { val hoge = new Hoge println(hoge.name) // クラスとオブジェクトが同じ名前なのでprivateメンバーにアクセスできる } }
class Hoge { private val name = "hoge" } object Fuga { // クラスとオブジェクトが同じ名前ではないのでエラーになる def printHogeName(): Unit = { val hoge = new Hoge println(hoge.name) } }
ちなみにクラスとオブジェクトが同じ名前じゃない場合は以下のようなエラーになります
// 上の例の場合 <console>:18: error: value name in class Hoge cannot be accessed in Hoge println(hoge.name)
Scalaプログラムを実行する方法
Scalaプログラムを実行するにはmain
メソッドを持つスタンドアロンオブジェクトを作る必要がある。
object Hoge { def main(args: Array[String]) = { for (arg <- args) println("arg = " + arg) } }
コンパイルを行うにはscalac
コマンドを使用する。
実行にはscala
コマンドを使用する。
$ scalac Hoge.scala $ scala Hoge foo bar baz arg = foo arg = bar arg = baz
Appトレイトを使うとmain
メソッドを省略できる
// Appトレイトを使うとmainメソッドを省略できる object Hoge extends App { for (arg <- args) println("arg = " + arg) }
第5章 基本型と演算子
※基本的にJavaと変わらないため、Javaとの違いを中心に書いています。
ダブルクォートを3個続けると生の文字列を表現できる
特殊文字を文字列に含めたい場合、普通はエスケープしないといけないが、ダブルクォートを3つ使うと特殊文字をエスケープしなくても出力などが可能になる。
// 通常の出力 scala> println("\\\"\'\\n\\t\\r") \"'\n\t\r // ダブルクォートを3つ使った場合 scala> println("""\"'\n\t\r""") \"'\n\t\r
Scalaではシンボルリテラルを作ることができる
シンボルリテラルを作るには'シンボル名
のように'
をシンボル名の前に入れる。
同じシンボル名はすべて同じSymbolオブジェクトを参照するので少し注意が必要。
scala> val s = 'aSymbol
s: Symbol = 'aSymbol
Scalaでは文字列リテラルを加工して式に含めることができる
文字列の前にs
を、文字列中に$
を入れることで文字列に式を含めることができる
scala> s"The answer is ${6 * 7}" res5: String = The answer is 42 scala> val name = "Luke" name: String = Luke scala> s"Use the Force $name" res6: String = Use the Force Luke
f
を使用すると書式を指定できる
// 書式を指定しない場合 scala> s"${math.Pi}" res10: String = 3.141592653589793 // 書式を指定した場合 scala> f"${math.Pi}%.5f" res11: String = 3.14159
Scalaでは演算子はメソッドである
Scalaでは+
や-
といったメソッドだけでなくすべてのメソッドを演算子のように使うことができる
scala> val sum = 1 + 2 // 1.+(2)を呼び出している sum: Int = 3 scala> val sumMore = 1.+(2) sumMore: Int = 3 scala> val s = "Hello, World!" s: String = Hello, World! scala> s indexOf 'o' // s.indexOf('o')を呼び出している res0: Int = 4 scala> -2.0 res1: Double = -2.0 scala> (2.0).unary_- //前置、後置演算子の場合はunary_[演算子]を呼んでいる res2: Double = -2.0
またScalaの慣習ではメソッドが副作用を持つ場合()
をつけ、副作用を持たない場合は()
を省略する
scala> val s = "Hello, World!" s: String = Hello, World! // toLowerCaseには副作用がないので()はつけない scala> s.toLowerCase res3: String = hello, world!
オブジェクトが等価どうかを比較する場合は==
を使う
Scalaの==
はJavaのequals
と同じで、
Scalaのeq
はJavaの==
と同じ
scala> List(1,2,3) == List(1,2,3) res6: Boolean = true scala> List(1,2,3) eq List(1,2,3) res7: Boolean = false