昨日までJavaJavaしてた人がScalaを触ることになったときのためのメモ

Scalaを触ってみて調べた点。
今後も追記予定。
ど初心者なので、指摘等頂けると喜びます。

---
* 2020/05/16
    * コメントいただいた点を反映しました。
    * @htsign さん 、@ka2kama さん ありがとうございました。

---

## 検証環境
* Windows10
* IntelliJ IDEA : 2019.1.2
* Scala : 2.12.7
* SBT : 1.3.10

## Scalaとは

>Scala（スカラ、SKAH-lah[2]）はオブジェクト指向言語と関数型言語の特徴を統合したマルチパラダイムのプログラミング言語である。名前の「Scala」は英語の「scalable language」に由来するものである（Wikipediaより）

[Scala - Wikipedia](https://ja.wikipedia.org/wiki/Scala)

## 開発環境作成

IntelliJ IDEA を使用する。
以下に導入方法と簡単なチュートリアルがある。

* [Intellij で Scala を始める | Scala Documentation](https://docs.scala-lang.org/ja/getting-started/intellij-track/getting-started-with-scala-in-intellij.html)

## 構文

### objectとclassの違いは？

> 1. object
> 　・シングルトンオブジェクトを示す。
> 　・シングルトンオブジェクトは自動でインスタンスが生成されるため、明示的にインスタンスを生成することは出来ない。
> 　・メソッドに対しては"オブジェクト名.メソッド名"でメソッドにアクセスする。
> 　・私は最初Javaのstaticみたいだなと思ったが、objectは唯一のインスタンスであることを示すだけであり、Scalaとしてstaticをサポートはしていないとのこと。
> 
> 2. class
> 　・シングルトンではないクラスを示す。
> 　・シングルトンとは違い自動でインスタンスは生成されないため、明示的にインスタンを生成する必要がある。
> 　・メソッドに対しては"インスタンス名.メソッド名"でメソッドにアクセスする。
> 

ざっくり言うとobjectはシングルトンで、classはそうではないということらしい。

#### 参考
* [【Scala】classとObjectの違いについて - ShikaShikaMemoの日記](http://shikashikamemo.hatenablog.com/entry/2014/04/07/220341)
* [Scalaのclassとobjectの違い - Qiita](https://qiita.com/Fujita234/items/b73acb81b58e66076488)

### インスタンスの作成方法
Javaと同じで普通にnewで作れるが、`apply`メソッドを定義することでnewがなくてもインスタンスを作成できる。

```scala
object Sample extends App {
  val hoge: Hoge = new Hoge
  hoge.hoge()

  //Fuga,Piyoはnewがなくてもインスタンスが作成できる
  val fuga = Fuga()
  fuga.fuga()

  val piyo = Piyo()
  piyo.piyo()
}

//通常
class Hoge {
  def hoge() = println("hogehoge")
}

// case class とすることでapplyが定義されnewが不要となる
case class Fuga() {
  def fuga() = println("fuga")
}

//コンパニオンオブジェクト
class Piyo() {
  def piyo() = println("piyo")
}

object Piyo {
  //applyを定義することでnewが不要となる
  def apply(): Piyo = new Piyo()
}
```



### 関数の定義方法

以下が関数定義の構文。
戻り値の型は暗黙的に評価できる場合は省略可能。
関数の内容が1行の場合は`{}`も不要。

```scala
def 関数名(仮引数名1 : 型, ...) : 戻り値の型 = { ... }
```


Int型を2つ引数に持つ戻り値がInt型のメソッド。

```scala
object Sample extends App {
  println(plus(2, 3))

  def plus(a: Int, b: Int): Int = {
    a + b
  }

  //上記は以下でも同じ
  def plus(a: Int, b: Int) = a + b
}
```

#### 参考
* [クラス · Scala研修テキスト](https://scala-text.github.io/scala_text/class.html)

### フィールドの宣言
class 直下に val, var で宣言する。

```scala
class Card(val _suit: Suit, val _rank: Int) {
  val suit = _suit
  val rank = _rank
  var value : String
}
```

コンストラクタでまとめることもできる。
上の例ではvalue以外はコンストラクタとまとめられる。

```scala
class Card(val suit: Suit, val rank: Int) {
  var value : String
}
```

### switch文の書き方
Scalaにswitch文はないので、match式で記述する。
`_` が `default` と同様の動きをする。

```scala
<対象式> match {
  case <パターン1> => パターン1結果
  case <パターン2> => パターン2結果
  case _ => デフォルト結果
}
```

```scala
  def toDisplayValue(): String = {

    rank match {
      case 1 => "A"
      case 11 => "J"
      case 12 => "Q"
      case 13 => "K"
      case _ => rank.toString
    }
  }
```

#### 参考
* [Scalaの制御構文 · Scala研修テキスト](https://scala-text.github.io/scala_text/control-syntax.html#match%E5%BC%8F)


### 三項演算子
Scalaに三項演算子はないので、if式を使う。

```scala
  val rank: Int = 11

  //Scalaではアクセサがあるので getXXX という書き方はあまりしないそう
  //  def getPoint(): Int = {
  //    if (rank > 10) 10 else rank
  //  }

  def point = if (rank > 10) 10 else rank
```

#### 参考
* [三項演算子 | その他 | プログラミング言語の比較 | hydroculのメモ](https://hydrocul.github.io/wiki/programming_languages_diff/etc/ternary.html)

### アクセサ

>Scalaではpublicなフィールドにはアクセサが自動的に定義される。

publicなフィールドはアクセス出来て当然だと思うのだが、厳密にはフィールドはprivateになり、publicアクセサが生成されているそう。
`getXXX`、`setXXX`ではなく`XXX`でアクセスするので、アクセサの命名は慣習に従う。

#### 参考
* [Scala におけるフィールド/プロパティの扱いを調べたんだけど相変わらず Scala 糖衣構文が多すぎる話 – たのしい人生](https://tanoshiilife.wordpress.com/2015/11/05/scala-%E3%81%AB%E3%81%8A%E3%81%91%E3%82%8B%E3%83%95%E3%82%A3%E3%83%BC%E3%83%AB%E3%83%89%E3%83%97%E3%83%AD%E3%83%91%E3%83%86%E3%82%A3%E3%81%AE%E6%89%B1%E3%81%84%E3%82%92%E8%AA%BF%E3%81%B9%E3%81%9F/)
* [備忘録的なblog: [Scala]アクセッサの定義](http://se-bikou.blogspot.com/2011/09/scala_25.html)


### 文字列の結合
Javaと同じで+演算子でできるが、文字列補完でもできる。

```scala
  //+演算
  override def toString = suit.mark + "の" + toDisplayValue

  //文字列補完
  override def toString = s"${suit.mark}の${toDisplayValue}"
```

#### 参考
* [猿でも分かるScala!：文字列の扱い - Qiita](https://qiita.com/msano/items/efd05e7677badf2efcf8)
* [文字列の補間 | Scala Documentation](https://docs.scala-lang.org/ja/overviews/core/string-interpolation.html)

### enum
Scalaには`enum`がない。

言語で定義されている`enumeration`は使いづらいらしく、`object`を作成して疑似的に作るのが主流のようだ。

```scala
sealed abstract class Suit(val mark: String) {
  def getMark() :String = mark
}

object Suit{
  case object SPADE extends Suit("スペード")
  case object HEART extends Suit("ハート")
  case object DIAMOND extends Suit("ダイヤ")
  case object CLUB extends Suit("クラブ")
}
```

* [ScalaのEnumerationは使うな - Scalaで列挙型を定義するには | Scala Cookbook](http://xerial.org/scala-cookbook/recipes/2012/06/29/enumeration)
* [Scalaで擬似列挙型を使うとき、case objectを使うか単純なobjectを使うか - Qiita](https://qiita.com/bigwheel/items/f5b29871f174923f7e80)

### Listの使い方

当記事への @ka2kama さんのコメントがとても詳しいのでリンク。

* [ka2kamaさんのコメント](https://qiita.com/aky100200/items/3b10218e06ee5d5b1445#comment-967422d2940d2a72b908)

---

* 型の宣言は[]を使う  

```scala
  var list : List[String]
```

* 初期化  

```scala
var list : List[String] = List("hoge","fuga")
```

* 要素の追加は ::  
    * イミュータブルなので新しいリストを返す。
* 注意
    * . は使わない。
    * <要素> :: List で追加する。
    * List :+ <要素> でも追加できるが効率が悪いので使わない方が良い。

```scala

  // . での :: の呼び出しはしない
  //  list = list.::("piyo")

  //要素が先
  list = "piyo" :: list

  // :+ でも要素追加できるが効率が悪いため使われないそう
  //  list = list :+ "piyo"

```

### コンストラクタの処理
class直下にそのまま記述する。

#### 参考
* [Scalaのクラスについて - Qiita](https://qiita.com/544/items/774e9a0bfed5507fad14)

### ループ

`for(要素 <- 配列)` でできる。
「要素 <- 配列」をジェネレータという。
ジェネレーターを複数書くことで多重ループを1つのforで記述することが出来る。

```scala
  var list: List[Account] = List()
  val names: List[String] = List("hoge", "fuga", "piyo")

  //ループ
  for (name <- names) {
    println(name)
  }

  //2重ループ
  for (name <- names) {
    for (i <- 1 to 3) {
      list = Account(i, name) :: list
    }
  }
  println(list)

  //上と同じ
  //ジェネレーターを複数書くことで多重ループを1つのforで記述することが出来る
  for (name <- names; i <- 1 to 3) list = Account(i, name) :: list
  println(list)
```

#### 参考
* [Scalaの制御構文 · Scala研修テキスト](https://scala-text.github.io/scala_text/control-syntax.html#for%E5%BC%8F)
* [Scala forメモ(Hishidama's Scala for Memo)](https://www.ne.jp/asahi/hishidama/home/tech/scala/for.html#h_for_loops)


### Listのシャッフル
Random.shuffleを使う。

```scala
    Random.shuffle(list)
```

* [ScalaでListのshuffle - sudixの日記](https://sudix.hatenadiary.org/entry/20130619/1371612878)

### Listの先頭を取得

以下のどちらでもできる。

```scala
    list(0)
    list.head
```

```scala
    val c: Card = bill.head
```

### Listから要素を削除
immutableなので削除したい要素をfilterして新たなlistを作成するという手順で疑似的に行う。

下記はどちらも同じ。

```scala
    list = list.filter(_ != "hoge")
    list = list.filterNot(_ == "hoge")
```

### 継承のパラメータ
自身のコンストラクタと同じ値を渡す。
Javaでいう`super(name)` みたいなことをしたい時には以下のようにする。

```scala
class User(name : String) extends AbstractPlayer(name) { ... }
```

### 標準入力
`readLine`を使う。
`Scanner#nextLine()` と同じ感じで使える。

```scala
  val str: String = readLine()
```

## 参考
タイトルをインスパイアさせていただきました。

* [昨日までJavaJavaしてた人がいきなりExcelのVBAを実装する羽目になったときのためのメモ - Qiita](https://qiita.com/opengl-8080/items/5bd8ae7fe95f5c31dfc3#%E5%8F%82%E8%80%83)