Scala:Object單例模式分析

ObjectClass區別

1.object與靜態類相似,類名加方法直接調用,不用new對象:

             Scala比 Java 更面向對象的一個方面是 Scala 沒有靜態成員。替代品是Scala的單例對象:singleton object。

2.Object()調用的是Object裏面的apply方法,val a = new ClassA()  a() 調用的是Class裏面的apply方法

   比如,var traffic=ArrayBuffer("a","b","c") 底層自動調用了apply方法

 

單例模式分析

使用Java的同學,對單例模式應該很熟悉了,在類的內部聲明一個private static 的自身類型的對象,然後通過一個static的方法返回即可。在Scala中,是沒有static這個東西的,但是它也爲我們提供了單例模式的實現方法,那就是 object(別混了,不是萬物之根的object)

Scala中使用單例模式時,除了定義的類之外,還要定義一個同名的object對象,它和類的區別是,object對象不能帶參數,先看一段實現代碼

/**這是我們定義的類
構造函數被我們定義爲private的,防止直接調用該類的構造來創建對象
*/
class StaticTest private {
  private def add_(x: Int, y: Int): Int = {
    return x + y
  }

  private def sub_(x: Int, y: Int): Int = {
    return x + y
  }
}

/**這個就是單例模式的定義,和類同名,且不帶參數*/
object StaticTest{
//內部聲明一個StaticTest類實例對象
  val singleObj = new StaticTest

  //applay方法,當執行 StaticTest() 時被執行
  def apply()={
    println("-------apply--------")
  }
  def add(x:Int,y:Int):Int={
  //調用StaticTest 類的方法
    return singleObj.add_(x,y)
  }
  //調用StaticTest 類的方法
  def sub(x:Int,y:Int):Int ={
    return singleObj.sub_(x,y)
  }

defmain(args:Array[String]):Unit={
//定義一個單例對象
val test=ObjectTest
//調用add方法
println(test.add(2,3))//5
}
}

 

這個類編譯後,會生成兩個文件StaticTest.class和StaticTest$.class,class和object被編譯到了一起

我們看一下StaticTest$.class類的反編譯結果,和我們的Java的單例模式就非常相似了。

public final class StaticTest$

{

 //指向自己,外部都通過MODULE$訪問接口

  public static final  MODULE$;

  //自身類型的內部靜態變量

  private final StaticTest singleObj;

  static

  {

    new ();

  }



  //這個就是對外接口,返回單例對象,很像我們經常用的getInstance

  public StaticTest singleObj()

  {

    return this.singleObj;

  }

  public int apply() {

Predef..MODULE$.println("-------apply--------");

  }



  public int add(int x, int y) {

    return singleObj().scala$test$StaticTest$$add_(x, y);

  }

  public int sub(int x, int y) {

    return singleObj().scala$test$StaticTest$$sub_(x, y);

  }



  //私有的構造

  private StaticTest$() {

    //指向自己

    MODULE$ = this;

    //創建對象

    this.singleObj = new StaticTest();

  }

}

 

再看看StaticTest.class的反編譯結果

public class StaticTest

{

  public static int sub(int paramInt1, int paramInt2)

  {

    return StaticTest..MODULE$.sub(paramInt1, paramInt2);

  }



  public static int add(int paramInt1, int paramInt2)

  {

    return StaticTest..MODULE$.add(paramInt1, paramInt2);

  }



  public static void apply()

  {

    StaticTest..MODULE$.apply();

  }



  public static StaticTest singleObj()

  {

    return StaticTest..MODULE$.singleObj();

  }



  public int scala$test$StaticTest$$add_(int x, int y)

  {

    return x + y;

  }



  public int scala$test$StaticTest$$sub_(int x, int y) {

    return x + y;

  }

}

static方法內通過MODULE$去訪問對外接口,也就是StaticTest$中的方法

 

經過上面分析,可以得知

1.單例對象會在第一次被訪問的時候初始化。

2.Scala中的單例模式,除了定義的類之外,還要定義一個同名的object對象

3.同名稱爲“伴生” ,object是class的伴生對象,class是object的伴生類

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章