3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Scala基礎

Posted at

Web上でサクッと試したい場合はScalaFiddleをば。

基本のき

コメント

// 一行コメント

/*
  複数行コメント
  複数行コメント
*/

文字出力

// 改行なし
print("出力したい内容")
// 改行あり
println("出力したい内容")

変数/定数

// 変数
var x: Int = 1
// 定数
val y: Int = 1

値の型は推論されるため省略可能。

// 型宣言である「: Int」の部分は値から推論されるため省略可能
val x = 1

四則演算

他のプログラミング言語と同様に+,-,*,/,%が利用可能。

println(1 + 1)  // 2
println(3 - 1)  // 2
println(4 * 2)  // 8
println(10 / 2) // 5
println(10 % 3) // 1

ブロック

{}を用いて処理をまとめることができる。
最終行が結果として評価される。なお、Scalaにもreturnは存在するが滅多に使わないらしい。

println({
  val x = 5
  val y = 2
  val z = 3

  val a = x + y
  a % z
}) // 1

制御文

条件分岐

if文

val age = 21

if (age < 20) {
  println("未成年")
} else {
  println("成人")
} // 成人

一行の場合、{}は省略可能。

if (age < 20) println("未成年")
else println("成人")

なお、Scalaに三項演算子はないがif-elseを用いて、それっぽく表現できる。

val x = 3
val ans = if (x % 2 == 0) "even" else "odd"
println(ans) // ans

match

他のプログラミング言語のswitchのようなもの。同じではない。

val lang = "EN"

val x = lang match {
  case "EN" => "ABCDE"
  case "JP" => "あいうえお"
  case _    => "other"
}

println(x) // ABCDE

色々特有の面白さがありそうだがややこいのでここでは省略。

繰り返し

繰り返しに関しては制御文より、Seqなどのコレクションタイプのメソッドを利用することが多い印象。正直あんまり使わないのでは。

while文

var i = 1
while(i <= 10) {
  println(i)
  i += 1
}
// 1
// 2
// 3
// 4
// 5

for文

for(x <- 1 to 5){
  println(x)
}
// 1
// 2
// 3
// 4
// 5

関数とメソッド

関数とメソッドの違いはよくわかってない。

関数

パラメータを受け取り、評価する式のこと。(パラメータ: パラメータの型) => 式と書く。
下記の例は受け取った値を2倍にする無名関数。

(x: Int) => x * 2

関数には名前を付与して宣言することも可能。
val 名前 = (パラメータ: パラメータの型) => 式と書く。

val double = (x: Int) => x * 2
println(double(3)) // 6
println(double(5)) // 10

パラメータを複数設定することや、パラメータなしにすることも可能。

val sum = (x: Int, y: Int) => x + y
println(sum(1, 2)) // 3
println(sum(5, 6)) // 11

val pi = () => 3.14
println(pi()) // 3.14

メソッド

defを用いて宣言をし、def 名前(パラメータ: パラメータの型): 戻り値の型 => 処理と書く。

def sum(x: Int, y: Int): Int = x + y
println(sum(1,2))

メソッドは複数のパラメータリストを受け取ることができる。

def addThenMultiply(x: Int, y: Int)(z: Int): Int = (x + y) * z
println(addThenMultiply(1, 2)(3)) // 9

複数行の処理がある場合、最終行の結果が戻り値となる。

def addThenMultiply(x: Int, y: Int)(z: Int): Int = {
  val sum = x + y
  sum * z
}
println(addThenMultiply(1, 2)(3)) // 9

クラス

クラス

classを用いてクラスを定義。class クラス名 {}と書く。
new クラス名()でインスタンスを生成

class Person {
  def greet(): Unit = println("Hi!")
}

val p = new Person()
p.greet() // Hi!

クラス名の後ろにコンストラクタパラメータを続けることでメンバを定義できる。

class Person(name: String) {
  def greet(): Unit = println("Hi! I'm " + name + ".")
}

val p = new Person("rokumura")
p.greet() // Hi! I'm rokumura.

ケースクラス

ケースクラスは不変であり、値で比較される
上述の通常のクラスはインスタンス同士の比較となる。
なお、ケースクラスはnewなしでインスタンス化できる。

// 通常のクラス
class Person(name: String) {}
val p1 = new Person("rokumura")
val p2 = new Person("rokumura")

if (p1 == p2) println("p1とp2は同じ")
else println("p1とp2は異なる")
// 値は同じだがインスタンスが異なるため「p1とp2は異なる」と判定される

// ケースクラス
case class CasePerson(name: String) {}
val c1 = CasePerson("rokumura")
val c2 = CasePerson("rokumura")

if (c1 == c2) println("p1とp2は同じ")
else println("p1とp2は異なる")
// インスタンスが異なるが値が同じであるため「p1とp2は同じ」と判定される

オブジェクト

オブジェクトは単一のインスタンスであり、シングルトンと考えることができる。
object 名前 {}と書く。

object Counter {
  private var num = 0
  def add(): Unit = num += 1
  def getNum(): Int = num
}

println(Counter.getNum()) // 0
Counter.add()
println(Counter.getNum()) // 1
Counter.add()
Counter.add()
println(Counter.getNum()) // 3

トレイト

フィールドとメソッドを持つ型。trait 名前 {}と書く。
振る舞いだけを宣言することも、実装を持つこともできる。
振る舞いのみを定義した場合、継承するクラス(継承にはextendsを用いる)は振る舞いの実装を強制される。
また、複数のtraitを継承することも可能。(class クラス名 extends トレイトA with トレイトBと書く)

trait Engineer {
  def develop(): Unit
}

class BackendEngineer extends Engineer {
  override def develop(): Unit = println("バックエンドを開発します")
}

class FrontendEngineer extends Engineer {
  override def develop(): Unit = println("フロントエンドを開発します")
}

val bEngineer = new BackendEngineer()
bEngineer.develop() // バックエンドを開発します

val fEngineer = new FrontendEngineer()
fEngineer.develop() // フロントエンドを開発します

同じトレイトを継承しているものは、抽象化した状態で扱うことができる。

val engineers: Seq[Engineer] = Seq(
  new BackendEngineer(),
  new FrontendEngineer()
) // Engineerの集合として扱い、それぞれがBackendかFrontendかは意識していない。

// 集合の各要素によって結果が変わる
engineers.foreach(e => e.develop())
// バックエンドを開発します
// フロントエンドを開発します

参考

ぶっちゃけ下記リンクを一読したほうが良い🍣

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?