Java職人がScalaやって覚えた基本を書いておく


# インストール

Windowsの場合、http://www.scala-lang.org/download/ からインストーラをダウンロードする。

Macの場合、`brew install scala`。

※事前にJREのインストールが必要。

# Scalaの特徴

* オブジェクト指向と関数型言語の特徴を併せ持つ静的型付け言語。
* JVM上で動作し、JavaのAPIやライブラリが使える。
* Javaより簡潔に書ける。
* Javaより強力な型推論。
* スクリプトが書ける。
* 演算子や制御構文を拡張できる。

# Hello World

## REPLでHello World

ScalaにはREPL(対話型インタープリター)が付属していて、コマンドラインから文を1行ずつ入力して実行する事ができる。
コマンドプロンプトから```scala```コマンドを引数なしで実行するとREPLが起動する。

```bash
$ scala
Welcome to Scala version 2.11.2 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_25).
Type in expressions to have them evaluated.
Type :help for more information.

scala> println("Hello Scala")
Hello Scala

scala> :q
$ 
```

## ScalaスクリプトでHello World

Scalaではスクリプトを作成する事ができる。
Scalaスクリプトファイルではクラスを定義せずにトップレベルから命令を書く。(クラスや関数を定義して使用する事も可能)

```scala:HelloScript.scala
println("Hello " + args(0))
```

実行は`scala`コマンドの第1引数でスクリプトファイル名を指定する。第2引数以降はスクリプトに渡す引数になる。

```bash
$ scala HelloScript.scala Scalaスクリプト
Hello Scalaスクリプト
$ 
```

## ScalaアプリケーションでHello World

アプリを作成するにはmainメソッドを持つシングルトンオブジェクトを作成する。

```scala:HelloApp.scala
object HelloApp {
  def main(args: Array[String]): Unit = {
    println("Hello " + args(0))
  }
}
```

Appトレイトを使用すると以下のように短く書けるようになる。

```scala:HelloApp.scala
object HelloApp extends App {
  println("Hello " + args(0))
}
```

実行は`scalac`コマンドでソースファイルをコンパイルしてから`scala`コマンドで行う。

```bash:
$ scalac HelloApp.scala && scala HelloApp Scalaアプリ
Hello Scalaアプリ
$ 
```

# Scalaのソースファイルの基本

* 拡張子は`.scala`。
* インデントはスペース２桁を推奨。
* トップレベルに定義するクラス名はファイル名と同じでなくても良い。
* トップレベルにpublicなクラスを複数定義できる。
* 文末のセミコロンは省略できる。
* アクセス修飾子を省略した時のデフォルトは公開。
* Scalaでは以下のパッケージとオブジェクトのメンバーを暗黙でインポートする。
    * [java.lang](http://docs.oracle.com/javase/jp/8/api/java/lang/package-summary.html)
    * [scala](http://www.scala-lang.org/api/current/#scala.package)
    * [scala.Predef](http://www.scala-lang.org/api/current/#scala.Predef$)

# 基本型

* Byte
* Short
* Int
* Long
* Char
* String
* Float
* Double
* Boolean
* Array

Javaではプリミティブ型とラッパークラスがあり、プリミティブ型はオブジェクトではないので特別な扱いが必要だったが、Scalaでは全てがオブジェクトとして扱える。

整数リテラルもIntクラスのオブジェクトなので以下のようにメソッドを呼び出す事もできる。

```scala
123.toString()
```

配列も特別な型ではなく、Javaのコレクションクラスのように型パラメータを持つArrayクラスのオブジェクトになる。

# 変数の定義

初期化後に再代入できない変数は`val`、再代入可能な変数には`var`を使用する。
型推論されるので型の指定は省略可能。

```scala
val a = 1
val b: Int = 2
// b = 2  //コンパイルエラー。val変数への再代入は不可。
var c = 3
var d: Int = 4
c = 5
d = 6
// c = "a"; //コンパイルエラー。型が違う値は再代入できない。
```

# 関数の定義

関数の定義は`def`を使う。

class内またはobject内に定義した関数はメンバーメソッドになる。
スクリプトではクラスの外側でも関数を定義できる。

```scala
class Class1 {
  def method1() {} // クラスClass1のメンバーメソッド
}
def func1() {} // クラスとは独立した関数
```

## 戻り値を返す関数

２つの整数値を受け取って整数値を返す関数は以下のようになる。

```scala
def sum(a: Int, b: Int): Int = { return a + b }
```

returnを書かなくても最後の式が戻り値になる。

```scala:
def sum(a: Int, b: Int): Int = { a + b }
```

式が1つの時は{}を省略できる。

```scala
def sum(a: Int, b: Int): Int = a + b
```

戻り値の型は型推論で省略できる。

```scala
def sum(a: Int, b: Int) = a + b
```

引数の型は省略できない。

## 戻り値がない関数

戻り値がない関数は戻り値の型を`Unit`にする。

```scala
def printText(text: String):Unit = println(text)
```

最後の式の結果が`Unit`なら戻り値の型を省略できる。

```scala
def printText(text: String) = println(text) //printlnの戻り値はUnitなのでこの関数の戻り値の型もUnitになる
```

関数本体の前に`=`を付けずに関数本体を{}で囲ってある場合は、最後の式が値を返してもこの関数の戻り値は`Unit`になる。

```scala
def func1(a: Int, b: Int) { sum(1, 2) } //戻り値はUnitになる
```
## 引数のデフォルト値

引数にデフォルト値を定義すると呼び出し時に省略可能になる。

```scala
def func1(a: Int = 0) = a + 1

println(func1(1)) // => 2
println(func1())  // => 1
```

# 関数リテラル

Java8でいうラムダ式。
関数を関数の引数に渡したり変数に代入する時に使用する。

```scala
val func1 = (a: Int, b: Int) => { a + b } : Int
```

戻り値の型を省略したり`{}`を省略できるのは関数定義と一緒。

```scala
val func1 = (a: Int, b: Int) => a + b
```

# クラスの定義

クラス`Hoge`に非公開フィールド`a`と公開メソッド`getA`を定義するには以下のようにする。

```scala
class Hoge {
  private val a = 3
  def getA() = a
}
```

クラス本体の`{}`は省略できる。

```scala
class Hoge
```

## 基本コンストラクタ

クラスのブロック内に書いたコードが基本コンストラクタの処理になる。

```scala
class Hoge {
  println("created.")
}

new Hoge() // => created.
```

以下のように書くと、基本コンストラクタで引数を受け取ってクラスのフィールドに設定してくれる。

```scala
class Hoge(private val a: Int)
```
上記はJavaで以下のように書いたのと同じ意味。

```java
public class Hoge {
    private int a;
    public Hoge(int a) {
        this.a = a;
    }
}
```

アクセス修飾子と`var/val`を省略すると`private val`になる。

```scala
class Hoge(a: Int)
```

基本コンストラクタのアクセス修飾子はクラス名と引数の間に指定する。

```scala
class Hoge private (a: Int)
```

## 補助コンストラクタ

基本コンストラクタ以外にコンストラクタを定義する時は`this`という名前のメソッドを使う。
補助コンストラクタでは最初に他のコンストラクタを呼ばなくてはならない。

```scala
class Hoge(a: Int) {
  def this(a: Int, b: Int) { this(a + b) }
}
```

## 親クラスのコンストラクタの呼び出し

```scala
class Parent(a: Int)
class Child extends Parent(1)
class Child(a: Int) extends Parent(a * 2)
```

## override

親クラスのメソッドをオーバーライドする時は`override`修飾子をつける。(アノテーションではない)

```scala
class Hoge {
  def f() = println("hoge")
}
class Meke {
  override def f() = println("meke")
}
```

# シングルトンオブジェクト

Javaではクラスに静的(static)メンバーを持つことができるが、Scalaではできない。
代わりにScalaではシングルトンオブジェクトを使用してそこにメンバーを定義する。

シングルトンオブジェクトの定義は`object`キーワードを使用する。

```scala
object Hoge {
  def method1() {}
}
```

使用する箇所ではJavaで静的メンバーを呼ぶのと同じ形式で呼び出す。

```
  Hoge.method1()
```


## コンパニオンオブジェクト

クラスと同じ名前のシングルトンオブジェクトを定義した場合はコンパニオンオブジェクトと呼ばれる。
コンパニオンオブジェクトはクラスと同じソースファイルに定義しなければならない。

```scala:Hoge.scala
class Hoge {
}
object Hoge {
}
```

## スタンドアロンオブジェクト

コンパニオンオブジェクトではないシングルトンオブジェクトは、スタンドアロンオブジェクトと呼ばれる。

# パッケージ

Scalaでは1ファイルに複数パッケージを書いたり、ネストしたりできる。

```scala:Javaと同じ1ファイル1パッケージの書き方
import package1
class Class1
```

```scala:1ファイルに複数パッケージを書く
import package1 {
  class Class1
}
import package2 {
  import package3 {
    class Class2
    class Object3
  }
}
```

# インポート

```scala:単一クラスのインポート
import package1.Class1
```
```scala:パッケージの全クラスのインポート
import package2.package3._
```
```scala:パッケージの指定クラスをインポート
import package2.package3.{Class2, Object3}
```
```scala:オブジェクトの全メンバーをインポート
import package2.package3.Object3._
```
```scala:パッケージのインポート
import package2.package3

new package3.Class2()
```

# 配列

サイズが3のInt配列を作成する。

```scala
val a = new Array[Int](3)
```

初期値を指定して配列を作成する。

```scala
val a = Array(1, 2, 3)
```

# if式

Scalaの`if`は式なので値を返せる。

```scala
val a = if (b == 1) 1 else 2
```

# ちょっと長くなったのでまとめ

だらだらと書いてたら長くなってしまったので終わりにする。

他にも以下は基本として覚えておかなければならないけど、またの機会にする。

* trait
* for式
* コレクション

# 参考

書籍
[Scalaスケーラブルプログラミング第2版](http://www.amazon.co.jp/Scala%E3%82%B9%E3%82%B1%E3%83%BC%E3%83%A9%E3%83%96%E3%83%AB%E3%83%97%E3%83%AD%E3%82%B0%E3%83%A9%E3%83%9F%E3%83%B3%E3%82%B0%E7%AC%AC2%E7%89%88-Martin-Odersky/dp/4844330845)

サイト
[Scala公式サイト](http://www.scala-lang.org/)
[Scalaメモ(Hishidama's Scala Memo)](http://www.ne.jp/asahi/hishidama/home/tech/scala/)