Kotlin使用心得(十):object與單例模式

Carter Chen
5 min readJun 20, 2018

--

“Single daisy blooms in a leafy green landscape” by Shane Rounce on Unsplash

寫在前面

本文將穿插大部分從以下這篇文章翻譯過來的內文:

我們將先從如何使用object實作單例模式(Singleton Pattern)開始探討,後續再介紹object的其它用法。

正文開始

Java有Java實現單例模式的方式,Kotlin也有,讓我們先從Java開始看吧!

在Java中實現單例模式

起手式:

  • 給一個名為「instance」的field
  • 調用getInstance()方法的時候,instance若為空,則實例化一個
  • 進行實例化的建構式訪問權限必須為private

做好啦:

但是這樣可能會有資料不同步的問題,加入synchronized關鍵字來保證安全性:

耶!我們大功告成~~~開趴囉~
在兼顧易讀性的狀況下,我們僅僅使用了18行代碼。

在Kotlin中實現單例模式

藉由使用object關鍵字,一行解決全世界:

Java開發者:……(覺得無言)

這種做法也稱為所謂的「Object Declaration」。

Kotlin實現單例模式背後的機制

可以試著decompile看看:

可以發現解開來的Java代碼,就是建立了一個唯一的實例。

object的其它用法

說好的建構式呢

剛剛我們已經用了Object Declaration實例化了一個物件。那objectclass一樣嗎?它一樣有建構式嗎?我們來編譯看看:

object Singleton()
object Singleton(arg1:Int)

Compiler:

Constructors are not allowed for objects

翻譯:你來錯棚了……用object不能使用建構式!

相等於Java的static用法

要使用相等於Java的static用法的話,你得在object關鍵字前加上companion關鍵字。以下面的代碼為例,加上companion後不管有沒有額外call Companion,都可以直接呼叫得到isDebug屬性:

當作匿名類別使用

先看範例,我們創造了一個Vehicle類別,CarTruck都是一種Vehicle,所以可以加入類型為Vehicle的列表vehicles

如果我們要快速增加一個匿名類別的話,可以搭配object使用所謂的「Object Expression」,我們來新增一個有10個輪子的Vehicle

vehicles.add(object : Vehicle("custom", 10) {})

這個新增的匿名類別,也是可以加入類型為Vehicle的列表vehicles 的:

來看看需要覆寫方法的情況,也是OK:

當作匿名物件使用

當我們需要一個物件,而且這個物件使用場景不多,不需要另外創建一個class的時候,可以考慮使用object

以上這種方式也是Object Expression的一種唷!

好了,來考考大家,當今天我們有兩個用object創造出來的匿名物件,物件中屬性的值都相同,甚至連方法都一樣,那這兩個物件是相等的嗎?

給你5秒鐘想想下面代碼println()出來的結果:

第一題:

println(shapeA==shapeB)

第二題:

println(shapeA===shapeB)

5

4

3

2

1

答案揭曉!

Compiler:

cannot be applied to ‘<no name provided>’ and ‘<no name provided>’

翻譯:哈哈,你被耍了,連編譯都無法編譯,根本不用比

因為我們用object建立出來的是匿名物件,類別為<no name provided>。
和匿名類別不一樣,匿名類別至少還繼承/實作了類別/介面,所以下次別被騙辣。

object用法,需要注意的地方

Object Declaration與Object Expression有本質上的差異,請大家多多注意:

  • Object Declaration是在第一次被訪問到時,延遲初始化用的
  • Object Expression是立即初始化的

--

--