作者:Antonio Leiva 時間:Jun 20, 2017 原文鏈接:https://antonioleiva.com/objects-kotlin/ Kotlin對象是Android開發人員不熟悉的另一個語言元素,因為在Java中沒有這樣的東西。 事實上,對象就是具有單一實現的數據類型。所以 ...
時間:Jun 20, 2017
原文鏈接:https://antonioleiva.com/objects-kotlin/
Kotlin對象是Android開發人員不熟悉的另一個語言元素,因為在Java中沒有這樣的東西。
事實上,對象就是具有單一實現的數據類型。所以如果我們想在Java中找到類似的東西,那將是單例模式。在接下的內容中,我們將比較它們。
單例與對象
在Java中,單例不像聽起來那麼容易實現。通常可能會認為是這樣:
1 public class Singleton { 2 3 private Singleton() { 4 } 5 6 private static Singleton instance; 7 8 public static Singleton getInstance() { 9 if (instance == null) { 10 instance = new Singleton(); 11 } 12 13 return instance; 14 } 15 }
但是,這段代碼是危險的,特別是它被用於不同的線程中。如果有兩個線程同時訪問這個單例,就有可能產生這個對象的兩個實例。安全的代碼應該是:
1 public class Singleton { 2 3 private static Singleton instance = null; 4 5 private Singleton(){ 6 } 7 8 private synchronized static void createInstance() { 9 if (instance == null) { 10 instance = new Singleton(); 11 } 12 } 13 14 public static Singleton getInstance() { 15 if (instance == null) createInstance(); 16 return instance; 17 } 18 }
如你所見,創建一個有效的單例,你需要好幾行代碼。
那麼在Kotlin中是怎樣的?
1 object Singleton
你不需要更多的代碼。你可以用在 Tools --> Kotlin 中的 bytecode 工具展示其,然後用Decomplie 選項。也就是,你可以看到Kotlin團隊決定怎樣實現單例的。
當不確定其背後究竟發生了什麼時,我建議您使用這個工具。
對象聲明
聲明對象就如同聲明一個類。
作為例子,讓我們來聲明一個實現資料庫幫助的對象:
1 object MySQLOpenHandler : SQLiteOpenHelper(App.instance, "MyDB", null, 1) { 2 3 override fun onCreate(db: SQLiteDatabase?) { 4 } 5 6 override fun onUpgrade(db: SQLiteDatabase?, oldVersion: Int, newVersion: Int) { 7 } 8 9 }
這段代碼,你只需要用保留字object
替代class
,其他都相同。只需要考慮到對象不能有構造函數,因為我們不調用任何構造函數來訪問它們。
對象的實例在我們第一次使用時,被創建。所以這裡有一個懶惰實例化:如果一個對象永遠不會被使用,這個實例永遠不會被創建。
伴生對象(Companion Object)
每個類都可以實現一個伴生對象,它是該類的所有實例共有的對象。它將類似於Java中的靜態欄位。
實現的例子:
1 class App : Application() { 2 companion object { 3 lateinit var instance: App 4 private set 5 } 6 7 override fun onCreate() { 8 super.onCreate() 9 instance = this 10 } 11 12 }
在這例子中,我創建一個由Application
擴展的(派送)的類,並且在companion object
中存儲它的唯一實例。
lateinit
表示這個屬性開始是沒有值得,但是,在使用前將被賦值(否則,就會拋出異常)。
private set
用於說明外部類不能對其進行賦值。
註意:
你可能會認為,若App
是一個對象,而非一個類會很有意義的。如果這樣,由於Android框架實例化類的方式,在你嘗試時,你會發現應用程式啟動時就拋出異常。你需要App
成為一個類,如果你想要訪問它,你可以創建一個這個小的單例。
對象表達式
對象也能用於創建匿名類實現。
例如:
1 recycler.adapter = object : RecyclerView.Adapter() { 2 override fun onBindViewHolder(holder: RecyclerView.ViewHolder?, position: Int) { 3 } 4 5 override fun getItemCount(): Int { 6 } 7 8 override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): RecyclerView.ViewHolder { 9 } 10 11 }
例如,每次想要創建一個介面的內聯實現,或者擴展另一個類時,你將使用上面的符號。
但是一個對象也可以表示一個不存在的類。你可以在運行中創建它:
val newObj = object { var x = "a" var y = "b" } Log.d(tag, "x:${newObj.x}, y:${newObj.y}")
結論
對象對於Java 6開發人員來說是一個新概念,但有許多概念可以與現有的相關聯,所以你可以快速地學習使用它們。
如果你喜歡你讀的內容,我建議您查看以前的文章,可以學習到更多的Kotlin知識,或者在本書中,學習如何從頭開始創建完整的應用程式。