scala 是基於 java 的,所以 java 要先安裝好
scala 安裝完並設定環境變數後 (我安裝時已自動加了環境變數),在命令提示字元有 scala 可以用即可
IntelliJ -> File/Settings/Plugins,搜尋 scala 並安裝好重啟 Intellij
新增專案後,在專案按右鍵 Add Framework Support,選中 scala,這樣按右鍵就有新增 scala 的選項了
這系列文章使用的是 2.13.0 版做測試
※main 方法
object ScalaTest {
def main(args: Array[String]): Unit = {
println("xxx")
}
}
※args 為參數名稱
※檔名為 ScalaTest.scala
※基本常識
.Value and Variable:
val 為常數,一開始一定要賦值,和 js 一樣
val i: Int = 1,: Int 是確定它的型態
var 宣告變數如可以改變用這個
沒有前|後置遞增|減
沒有 static
沒有 switch,但有 case
※型態的繼承
Nothing -> Byte、Short、Int、Long、Float、Double、Char、Boolean、Unit -> AnyVal -> Any
Nothing -> Null -> List、Option、CustomClass -> AnyRef(java.lang.Object) -> Any
※ java 的八種型態全有,但 Int 和 Char 取名不同,然後多一種 Unit,相當於 java 的 void
※型態轉換規則
1.Byte -> Short -> Int -> Long -> Float -> Double
2.Char -> Int
3.不可強轉
val x: Int = 123456
val y: Float = x
// val z: Long = y
// val z: Long = (Long)y
val z: Double = y
※註解的兩行會編譯錯譯,沒有什麼強轉的
※宣告陣列
// 不定長度
println(Array(1, 2, 3).apply(0))
println(Array("a", "b", "c").apply(0))
// 固定長度
var arr = new Array[String](3)
println(arr(0))
arr(0) = "s"
println(arr(0))
// 多維陣列
var arr3 = Array.ofDim[String](2, 3, 4) // 內鍵到五維
arr3(0)(0)(0) = "000"
println(arr3(0)(0)(0))
println(arr3.length) // 2
println(arr3(0).length) // 3
println(arr3(0)(0).length) // 4
// 固定範圍陣列
val ints = Array.range(5, 10)
for(n <- ints){
println(n) // 5-9
}
val ints2 = Array.range(5, 17, 3)
for(n <- ints2){
println(n) // 5 8 11 14
}
※迴圈
while、do...while、for,只有 for 和 java 不一樣,只有 java 的增強型 for 迴圈,但中間不是 :,是 <-,還多出一種迴圈 叫 until
val value = List(1,2,3)
// for(v <- value){
// for(v <- 1 to 10){
for(v <- 1 until 10){ // 不包含10
println(v)
}
.多層迴圈
scala 的多層 for 迴圈可以一行就搞定,當然寫多行也是可以
for(i <- 1 to 9; j <- 1 to 9){
println(i + "x" + j + "=" + i * j)
}
for(i <- 1 to 3; j <- 1 to 3; k <- 1 to 3 if j != 2){
println(i + "-" + j + "-" + k)
}
※如上上兩層和三層的迴圈,後面還可以加 if
.儲存迴圈的值
var xxx = for{i <- 1 to 10 if i != 3; if i < 8}
yield i
for(x <- xxx) {
println(x) // 1 2 4 5 6 7
}
var xxx = for(i <- 1 to 10; j <- 1 to 3 if i != 3; if i < 8)
yield (i,j)
for(x <- xxx) {
println(x)
}
※不可以有實體 (花括號)
.中斷與繼續
break 和 continue,但 scala 沒有 continue
var loop = new Breaks;
for(v <- 1 until 10){
if(v == 7) loop.break()
println(v)
}
var loop = new Breaks;
for(v <- 1 until 10){
loop.breakable {
if (v == 7) loop.break()
println(v)
}
}
※new Breaks 後,break() 就是 break;breakable 就是 continue
※Method
格式為:def 方法名(方法參數): 回傳值 = {內容}
def showNum() = 9
println(showNum()) // 9
def showNum:Int = 9
println(showNum) // 9
def add(x: Int): Int = x + 1
println(add(7)) // 8
def add2(x: Int, y: Int):Int = x + y
println(add2(1, 2)) // 3
def add2(x: Int)(y: Int):Int = x + y
println(add2(1)(2)) // 3
※()可以用多個,但用多個時,呼叫也要用多個
※方法裡的方法
java 不允許方法裡再放方法,但 scala 可以
def accu(start:Int, end: Int): Int = {
if(start >= end) return 0
var vstart = start - 1
def accu2(acc: Int, end: Int): Int = {
//println("acc=" + acc + ", vstart=" + vstart)
if (vstart == end)
return acc
else
vstart += 1
accu2(acc + vstart, end)
}
accu2(0, end)
}
println(accu(0, 10))
※加總的程式
※類別
object ScalaTest {
def main(args: Array[String]): Unit = {
val a = new A
val b = new B()
val c = new C
val d1 = new D("k", 1)
println(d1.toString)
d1.customMethod(99)
val d2 = new D("k")
println(d2.toString)
val e = new E(value=1)
println(e.toString)
}
class B() {}
class C
class D(var key:String, value:Int = 0) {
override def toString: String = s"($key, $value)"
def customMethod(xx: Int): Unit = {
println(xx)
}
}
class E(var key:String="xxx", value:Int) {
override def toString: String = s"($key, $value)"
}
}
class A {}
※也有內部類別,類別和建構子整合在一起,如果是空的參數,可以省略圓括號
※建構子可以有預設值,這樣就有 overloading 了
※使用 s"($xxx)" 可取得參數值
※class E,第一個建構子有預設值,如果第一個參數給 null,就真的抓到 null 了
※建構子中,有 val、var 時,new 完才可看見,如果不寫就是 private
※訪問修飾子
public、protected、private
以 java 來對比的話,沒有預設不寫的修飾子
protected 只有子類別可訪問,同包不行,這點和 java 不同
.作用域
可以在修飾子後面用方括號包起一個類別
如 private[.ooo.Xxx] :表示除了 Xxx 這個類別外,其他都是 private 的
※setter/getter
class Xxx {
private var pid: Int = 0
def id = pid
def id_= (id: Int): Unit = {
this.pid = id
}
// def setId(id: Int): Unit = {
// this.id = id
// }
//
// def getId() :Int = {
// this.id
// }
private def add(x: Int): Int = x + 1
}
val x = new Xxx()
x.id = 999
println(x.id)
※註解的部分是 java 的寫法,也是可以用
※setter 宣告方法:
1.宣告一個外面看不見的變數 (pid)
2.宣告一個外面看的見的變數 (id),這樣外面才可以用這個名稱,
3.然後再宣告一個方法,是 2 的後面加 _=,在 scala 表示 setter
※getter 就是變數名稱 (pid)
※沒有特別寫修飾子,預設是 public,但這個字不能寫,會編譯錯誤
※case
類似 java 的 switch
def xxx(str: String):Int = str match {
case "a" => 1
case "b" => 2
// case _ => 3
}
println(xxx("c"))
※匹配 _ 就是當什麼都匹配不到時用的,此例會報錯,必須將註解打開
※不需要也不能寫 break
※case class
在 scala 可以將 case 用在 class
case class Animal(id: Int, name: String)
val a1 = Animal(1, "dragon")
val a2 = Animal(2, "dragon")
val a3 = Animal(1, "dragon")
val a4 = new Animal(1, "dragon") // 可省略 new
println(a1 == a2) // false
println(a1 == a3) // true
println(a1 == a4) // true
.迴圈判斷
val list = List(
Animal(1, "pig"),
Animal(2, "dog"),
Animal(3, "chicken")
)
for(l <- list) {
l match {
case Animal(1, "pig") => println("I'm pig")
case Animal(2, "dog") => println("I'm dog")
case _ => println("Who am I")
}
}