如果 object 的名稱和 class 名稱相同,稱為 Companion Object (Employee).
由於 Companion Object 是要將 trait 與 object 定義在同一個檔案裡,但由於這邊是使用 REPL 做 demo,
所以再用一個 object(Emp) 把它們包起來,否則 REPL 的環境不會被視為是 Companion Object,如果是定義在一個 Employee.scala 檔案裡,則不用 Emp 包起來 :
scala> import scala.collection.mutable.ListBuffer
import scala.collection.mutable.ListBuffer
scala> object Emp {
|
| class Employee(val salary: Int)
|
| object Employee {
|
| private val emps: ListBuffer[Employee] = new ListBuffer[Employee]
|
| private var sum = 0
|
| def addEmp(emp:Employee) = emps += emp
|
| def sumSalary = {
| emps.foreach(emp => sum += emp.salary)
| sum
| }
| }
| }
defined object Emp
scala> Emp.Employee.addEmp(new Emp.Employee(10))
res0: scala.collection.mutable.ListBuffer[Emp.Employee] = ListBuffer(Emp$Employee@35eee641)
scala> Emp.Employee.addEmp(new Emp.Employee(20))
res1: scala.collection.mutable.ListBuffer[Emp.Employee] = ListBuffer(Emp$Employee@35eee641, Emp$Employee@4f3c7808)
scala> Emp.Employee.sumSalary
res2: Int = 30
就是將參數傳給(apply) function 的意思
scala> val sum = (num1:Int,num2:Int) => num1 + num2
sum: (Int, Int) => Int = $$Lambda$1197/530446114@3f06abd
scala> sum(2,3)
res15: Int = 5
scala> sum.apply(2,3)
res14: Int = 5
將參數傳給(apply) object
scala> object Counter {
| val baseNum = 10
| def apply(num1:Int , num2:Int) = baseNum + num1 + num2
| }
defined object Counter
scala> Counter(2,3)
res16: Int = 15
定義 :
a(x) = y 相當於 a.update(x, y),a(x,y) = x 相當於 a.update(x,y,z) 以此類推.
scala> class Cellphone {
|
| val numbers = scala.collection.mutable.Map[String,(Int,Int)]()
|
| def apply(name:String) = numbers(name)
| def update(name:String, number:(Int,Int)) = numbers(name) = number
| }
defined class Cellphone
scala> val phonebook = new Cellphone
phonebook: Cellphone = Cellphone@1d9af731
會呼叫 Cellphone 的 update 方法 :
scala> phonebook("Daniel")=(123,45678)
scala> phonebook("Sam")=(321,876543)
會呼叫 Cellphone 的 apply 方法 :
scala> phonebook("Daniel")
res5: (Int, Int) = (123,45678)
scala> phonebook("Sam")
res6: (Int, Int) = (321,876543)
apply 可以設計成為 factory pattern :
scala> object Trans {
| trait Transportation {
| def go
| }
| object Transportation {
| private class Car extends Transportation {
| override def go {println("drive car")}
| }
| private class Boat extends Transportation {
| override def go {println("drive boat")}
| }
| def apply(name:String): Transportation = {
| if(name == "car") {
| new Car
| } else {
| new Boat
| }
| }
| }
| }
defined object Trans
scala> val car = Trans.Transportation("car")
car: Trans.Transportation = Trans$Transportation$Car@178cfe5e
scala> car.go
drive car
scala> val boat = Trans.Transportation("boat")
boat: Trans.Transportation = Trans$Transportation$Boat@31e90355
scala> boat.go
drive boat