我們在使用scala的時候經常會用到對象的apply方法和update方法。
雖然我們表面沒有察覺,但是實際上兩個方法都會遵循相關約定被調用。
apply
apply方法的約定:用括號傳遞給變量(對象)一個或多個參數的時候,會把它轉換成對apply方法的調用。
我們先看一個例子。
class ClassApplyTest{ //類的apply方法調用示例
def apply(param:String): String ={
println("apply method called,the paramter is "+param);
"Hello,world";//返回值
}
}
object Main{
def main(args:Array[String]): Unit ={
val myApply = new ApplyTest;//實例化ApplyTest
println(myApply("param1"));//傳入參數param1
}
}
輸出結果
apply method called,the paramter is param1
Hello,world
我們從上個例子看到,我們給ApplyTest類實例一個對象myApply,然后給myapply傳入了param1的參數。
過程中並沒有調用對象的apply方法,myapply對象自己調用了apply方法。
我們再看一個例子
object SingleObjectApplyTest{//單例對象的apply方法調用示例
def apply(param1:String,param2:String):String = {
println("apply method called");
param1+" and "+param2;
}
def main(args:Array[String]): Unit ={
val myApply = SingleObjectApplyTest("zyh","zqy");
//注意,我們這里建的是單例對象不是類,並不用new關鍵字。
println(myApply);
}
}
輸出結果
apply method called
zyh and zqy
我們定義了一個單例對象,並在對象中定義了apply方法。
當我們建立單例對象並傳參的時候自動調用了apply方法返回了param1 and param2到了myApply。
class ClassAndObjectApplyTest{ //伴生類和對象apply方法的結合使用
}
class ApplyTest{
def apply()={
println("apply method in class is called.");
}
def greetingFromClass = println("Greet method is called.");
//沒有參數的時候可以省略圓括號
}
object ApplyTest{
def apply() = {
println("apply method in object is called.");
new ApplyTest;//返回一個ApplyTest類型的實例
}
}
object ClassAndObjectApplyTest{
def main(args:Array[String]): Unit ={
val myApply = ApplyTest();//ApplyTest伴生對象的調用,這里的括號一定不能省略
//注意,我們這里沒有new關鍵字,是對ApplyTest的伴生對象的調用
//伴生對象會自動調用伴生對象的apply方法
myApply.greetingFromClass;
myApply();
//ApplyTest伴生類的調用
//然后自動調用了伴生類的apply方法
}
}
輸出結果
apply method in object is called.
Greet method is called.
apply method in class is called.
我們這個例子包含了兩對的伴生類和對象。
因為我們這里並沒有任何參數,所以我們這里使用()就是向其傳入參數。
我們在調用ApplyTest伴生對象並傳參的時候,自動調用了ApplyTest伴生對象的apply方法,返回一個ApplyTest伴生類的一個實例對象。
我們可以通過ApplyTest伴生類的對象訪問類中的方法,雖然被實例化了但是並沒有傳遞參數,所以並沒有調用其apply方法。
當我們執行myApply()的時候是對ApplyTest伴生類傳參的操作,因為沒有參數,所以只加了圓括號,然后自動調用其apply方法。
下面看一個scala語法中的apply的例子
val myStrArr = Array("BigDate","Hadoop","Spark");
注意到,我們在定義數組的時候,並沒有像Java那樣需要使用new關鍵字創建,
沒有new實例,並不能用構造器創建,而且還直接傳遞了三個參數,怎么創建的呢?
其實這里,scala就會自動轉換成對Array的伴生對象apply方法的調用,完成數組的建立和初始化。
update
update方法的約定:當對帶有圓括號並包括一到若干參數的對象進行賦值時,編譯器將調用對象的update方法。
在調用時,是把括號里的參數和等號右邊的對象一起作為方法的輸入參數來執行調用。
示例
val myStrArr = new Array[String](3);//聲明一個長度為3的字符串數組
myStrArr(0) = "BigDate";//這里正好符合了update方法的調用規則
//調用了伴生類的Array的update方法
//執行了myStrArr.update(0,"BigDate")
從上個例子可以看出,在進行數組賦值的時候,之所以沒有向java一樣采用了myStrArr[0]這樣的賦值的方式,
而是采用了update方法的賦值機制,為了能觸發update方法的機制,所以才使用myStrArr(0)這樣圓括號的形式進行賦值。
