Unlimited Plugins, WordPress themes, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Code
  2. Kotlin

Kotlin從零開始:类和對象

by
Difficulty:IntermediateLength:LongLanguages:
This post is part of a series called Kotlin From Scratch.
Kotlin From Scratch: Advanced Functions
Kotlin From Scratch: Advanced Properties and Classes

Chinese (Traditional) (中文(繁體)) translation by Zhang Xiang Liang (you can also view the original English article)

Kotlin是壹種編譯為Java字節碼的現代編程語言。它是免費的,  開源,並有望使Android開發更有趣。 

在  前面的文章中,您學習了Kotlin中函數的高級用法,例如擴展函數,閉包,高階函數和內聯函數。 

在本文中,您將通過了解Kotlin中的面向對象編程入門:構造函數和屬性,轉換以及Kotlin變得更加簡單的更高級的類功能。 

1. 類

類是壹個程序單元,將功能和數據分組在壹起以執行壹些相關的任務。我們使用class關鍵字(類似於Java)在Kotlin中聲明壹個類。 

前面的代碼是最簡單的類聲明 - 我們只創建了壹個名為的空類  Book。即使它不包含使用其默認構造函數的主體,我們仍然可以實例化此類。 

正如妳可以在上面的代碼中看到的那樣,我們沒有使用new關鍵字來實例化這個類,就像在其他編程語言中那樣。 new在Kotlin中不是關鍵字。 這使得我們的源代碼在創建類實例時變得簡潔。但請註意,在Java中實例化Kotlin類將需要new關鍵字。  但請註意,在Java中實例化Kotlin類將需要new關鍵字。 

類構造函數和屬性

讓我們來看看如何為我們的類添加構造函數和屬性。但首先,讓我們看壹下Java中的典型類:

讓我們來看看如何為我們的類添加構造函數和屬性。但首先,讓我們看壹下Java中的典型類:

  • 兩個領域:titleisbn
  • 壹個構造函數
  • 這兩個領域的getter和setter(幸運的是,IntelliJ IDEA可以幫助我們生成這些方法)

現在讓我們看看我們如何在Kotlin中編寫前面的代碼:

壹個相當整潔的類!我們現在已經將代碼行數從20減少到了9.該constructor()函數在Kotlin中稱為次級構造函數。 這個構造函數等同於我們在實例化類時調用的Java構造函數。  

在Kotlin,沒有像妳可能熟悉的領域概念; 相反,它使用“屬性”的概念。 例如,我們已經宣布與兩個可變(讀寫)性能var關鍵字:titleisbnBook類。 (如果您需要對Kotlin中的變量進行更新,請參閱本系列的第壹篇文章:  變量,基本類型和數組。)

令人驚奇的是,這些屬性的getters和setter是由Kotlin編譯器為我們自動生成的。  請註意,我們沒有為這些屬性指定任何可見性修飾符,因此默認情況下它們是公共的。換句話說,他們可以從任何地方訪問。 

讓我們來看看Kotlin中同壹個類的另壹個版本:

在這段代碼中,我們刪除了第二個構造函數。 相反,我們在稱為主構造函數的類頭中聲明了壹個構造  函數。 請註意,  init 代碼塊在創建類實例時立即執行。 正如妳所看到的,我們的代碼仍然有很多樣板。

 正如妳所看到的,我們的代碼仍然有很多樣板。

我們的Book類現在只是壹行代碼。太棒了!請註意,在主構造函數參數列表中,我們定義了可變屬性:  titleisbn 直接在主構造函數中使用var關鍵字。 

我們也可以將默認值添加到構造函數中的任何類屬性中。

事實上,我們也可以省略  constructor關鍵字,但只有當它沒有任何可見性修飾符(publicprivate,或  protected)或任何註釋。 

壹個非常整潔的類,我必須說! 

我們現在可以像這樣創建壹個類實例:

访问和设置属性

在Kotlin中,我們可以通過類對象獲取屬性book,然後是點分隔符  .,然後是屬性名稱title。這種訪問屬性的簡潔風格稱為  屬性訪問語法。 換句話說,我們不必調用屬性getter方法來訪問或調用setter來設置Kotlin中的屬性,就像我們在Java中所做的那樣。

由於該  isbn 屬性是使用  var 關鍵字(讀寫)聲明的,因此我們也可以使用賦值運算符更改屬性值=

我們來看另壹個例子: 

在這裏,我們isbn使用val關鍵字將參數更新為不可變(只讀)。我們實例化了壹個類實例,book並重新分配了title屬性值“Things Fall Apart Apart”。 請註意,當我們試圖重新分配isbn屬性值時1234,編譯器抱怨道。這是因為該屬性是不可變的,已經用val關鍵字定義。

Java互操作性

請註意,通過var 在主構造函數中聲明帶有修飾符的參數  ,Kotlin編譯器(幕後)幫助我們生成了屬性訪問器:getter和setter。如果妳使用  val,它將只產生getter。 

這意味著Java調用者可以通過分別調用屬性的setter或getter方法來簡單地獲取或設置屬性字段。請記住,這取決於用於定義Kotlin屬性的修飾符:var或val。 

自定義Getters和Setters

在本節中,我將向您展示如何在Kotlin中為屬性創建自定義訪問器(getter和setter)。 如果要在將值設置為類屬性之前驗證或驗證值,則創建自定義設置器可能很有用。並且,當您想要更改或修改應該返回的值時,自定義屬性獲取器可能很有用。  

創建壹個自定義設置器

因為我們要為屬性創建自己的自定義getter或setter,所以我們必須在類體中定義該屬性,而不是構造器標題。   

這就是為什麽我們將mutable(讀寫)  title 屬性移動到類體中並給它壹個默認值(否則它不會編譯)。   

妳可以看到我們 在屬性定義set(value) 的  title右下方定義了我們自己的setter方法  - 註意妳不能修改這個  set() 方法簽名,因為這是編譯器期望的自定義屬性設置函數。 

value 傳遞給該  set 方法的參數  表示由用戶分配給該屬性的實際值 - 如果願意,可以更改該參數名稱,但是  value 更受歡迎。 我們  value 通過檢查值是否為空來驗證。如果為空,則停止執行並拋出異常; 否則,將該值重新分配給壹個特殊  field 變量。

我們  value 通過檢查值是否為空來驗證。如果為空,則停止執行並拋出異常; 否則,將該值重新分配給壹個特殊  field 變量。

創建壹個自定義的Getter

為Kotlin中的壹個屬性創建壹個自定義getter非常簡單。

在該get方法內部,我們簡單地返回壹個修改  field- 在我們的情況下,我們用大寫字母返回了書名。

請註意,每次我們為該title屬性設置壹個值時,其set方法塊都會執行 -  get 每次我們檢索時,方法都是壹樣的。 

如果您想了解Kotlin類(在類,對象或接口中定義的函數類型)的成員函數,請訪問 本系列中的More Fun With Functions發布。 

更多關於構造函數

正如我前面所討論的,我們在Kotlin中有兩種類型的構造函數:小學和中學。我們可以自由地將它們結合在壹個類中,如下例所示: 

請註意,我們不能像在主構造函數中那樣在次構造函數中聲明屬性。如果我們想這樣做,我們必須在類體內聲明它,然後在二級構造函數中初始化它。    

在上面的代碼中,我們設置了new該類的屬性的默認值Car(請記住,new不是Kotlin中的關鍵字) - 然後,如果需要,我們可以使用輔助構造函數進行更改。在Kotlin中,每個輔助構造函數都必須調用主構造函數,或者調用另壹個調用主構造函數的輔助構造函數 - 我們使用this關鍵字來實現該構造函數  。

 還要註意,我們可以在壹個類中有多個二級構造函數。 

如果壹個類擴展了壹個超類,那麽我們可以使用super關鍵字(類似於Java)來調用超類的構造函數(我們將在未來的帖子中討論Kotlin中的繼承)。 

正如我前面所說,為了我們明確地將可見性修飾符包含到類中的構造函數中,我們必須包含constructor關鍵字 - 默認情況下,構造函數是公共的。 

在這裏,我們將構造函數設為private - 這意味著用戶無法直接使用其構造函數實例化對象。如果您希望用戶調用另壹個方法(工廠方法)間接創建對象,這可能很有用。 

2.任何和無類型

在Kotlin中,類型層次結構中最高的類型被調用Any。這相當於Java Object類型。  這意味著,在科特林所有類明確地從繼承  Any的類型,包括  String,  IntDouble,等等。該Any類型包含三種方法:   equals,  toString,和hashcode

我們還可以Nothing在Kotlin中的類中使用總是返回異常的函數 - 換句話說,對於不能正常終止的函數。當函數返回時Nothing,我們知道它會拋出異常。在Java中不存在這種類型。   當函數返回時Nothing,我們知道它會拋出異常。在Java中不存在這種類型。 

在單元測試中測試錯誤處理行為時,這可以派上用場。   

3.可見性修飾符

可見性修飾符幫助我們限制我們的API對公眾的可訪問性。我們可以為我們的類,接口,對象,方法或屬性提供不同的可見性修飾符。Kotlin為我們提供了四種可見性修飾符: 

Public

這是默認設置,任何具有此修飾符的類,函數,屬性,接口或對象都可以從任何地方訪問。 

Private

聲明為頂級函數,接口或類private只能在同壹個文件中訪問。 

private在類,對象或接口內聲明的任何函數或屬性只能對同壹類,對象或接口的其他成員可見。

Protected

所述protected 改性劑可以僅被應用到性能或功能內的類,對象或接口不能被應用於頂層函數,類或接口。使用此修飾符的屬性或函數只能在定義它的類和任何子類中訪問。 

Internal

在具有模塊(Gradle或Maven模塊)的項目中,internal 只能在該模塊中訪問使用該模塊內聲明的修飾符指定的類,對象,接口或函數。 

4.智能Casting

Casting意味著采用另壹種類型的對象並將其轉換為另壹種對象類型。例如,在Java中,我們使用instanceof運算符來確定特定的對象類型是否屬於其他類型,然後再進行轉換。 

正如妳所看到的,我們檢查了shape實例是否是Circle,然後我們必須明確地將shape引用轉換為Circle類型,以便我們可以調用circle類型的方法。 

關於Kotlin的另壹個令人敬畏的事情是編譯器在編譯時的智能。現在讓我們看看Kotlin的壹個版本。

很簡約!編譯器很聰明,知道if只有當shape對象是壹個實例時才會執行該塊Circle,因此投影機制在我們的引擎下完成。 現在我們可以輕松地調用Circle該if塊內的屬性或類型的函數。

 這裏,在最後壹個條件&&if頭會被調用,只有當第壹個條件是true。如果shape不是Circle,那麽最後的條件將不會被評估。 

5.明確的Casting

我們可以使用as操作符(或不安全的轉換操作符)將類型的引用顯式轉換為Kotlin中的另壹種類型。 

如果顯式的轉換操作是非法的,請註意a ClassCastException會被拋出。為了防止在投射時拋出異常,我們可以使用安全的投射運算符as(或可為空值的投射運算符)  ?。 

as?運營商將嘗試轉換為預期的類型,並返回  null 如果該值不能代替投拋出異常。  請記住, 本系列中的Nullability,Loops和Conditions發布中的Nullability部分討論了類似的機制  。閱讀那裏進行復習。 

6.  對象

Kotlin中的對象比Java對象更類似於JavaScript對象。請註意,Kotlin中的對象不是特定類的實例!

對象與類非常相似。以下是Kotlin中對象的壹些特征:

  • 他們可以擁有屬性,方法和  init塊。
  • 這些屬性或方法可以具有可見性修飾符。
  • 他們不能有構造函數(小學或中學)。
  • 他們可以擴展其他類或實現壹個接口。

現在我們來深入探討如何創建壹個對象。  

我們將object關鍵字放在我們想要創建的對象的名稱之前。實際上,當我們使用object構造在Kotlin中創建對象時,我們正在創建單例,因為只有壹個對象的實例存在。 當我們討論與Java的對象互操作性時,您將會學到更多。  當我們討論與Java的對象互操作性時,您將會學到更多。 

單例是壹種軟件設計模式,它保證壹個類只有壹個實例,並且該類提供了壹個全局訪問點。 無論何時多個類或客戶要求類,他們都會得到同壹類的實例。 您可以查看我的關於Java中的單例模式的文章以了解更多信息。 

您可以訪問項目中任何位置的對象或單例 - 只要您導入它的包。

如果您是Java編碼人員,那麽我們通常會創建單例:

正如您所看到的,使用Kotlin object構造可以簡化創建單例。

Kotlin中的對象也可以用來創建常量。通常在Java中,我們通過將其設置為公共靜態final字段來在類中創建常量: 

Java中的這些代碼可以更簡潔地轉換為Kotlin,如下所示:

在這裏,我們APIConstantsbaseUrl 壹個包內的屬性聲明常量com.chike.kotlin.constants。在底層,baseUrl我們為我們創建了壹個Java私有靜態最終成員,並使用字符串URL進行了初始化。 

要在Kotlin的另壹個包中使用此常量,只需導入包。

Java互操作性

Kotlin將對象轉化為引擎蓋下的最終Java類。這個類有壹個私有的靜態字段INSTANCE,它包含壹個類的單個實例(單例)。以下代碼顯示了用戶如何從Java調用Kotlin對象。 

在這裏,調用的Java類Singleton是使用公共靜態最終成員生成的INSTANCE,其中包括公共final函數myFunc()。 

為了使Kotlin中的對象函數或屬性成為生成的Java類的靜態成員,我們使用@JvmStatic註釋。以下是如何使用它: 

通過應用@JvmStatic註釋myFunc(),編譯器將其轉換為靜態函數。

現在,Java調用者可以像調用普通的靜態成員調用壹樣調用它。請註意,使用INSTANCE靜態字段來調用成員將仍然有效。 

7.  Companion對象

現在我們已經了解了Kotlin中的對象,讓我們深入另壹種稱為伴侶對象的對象。

由於Kotlin不支持靜態類,方法或屬性,就像我們在Java中所使用的那樣,Kotlin團隊為我們提供了壹個更強大的替代方法,稱為伴隨對象。 伴侶對象基本上是壹個屬於類的對象 - 這個類被稱為對象的伴隨類。這也意味著我提到的對象的特征也適用於伴隨對象。

創建伴隨對象

類似於Java中的靜態方法,伴隨對象不與類實例相關聯,而與類自身相關聯 - 例如,工廠靜態方法,它具有創建類實例的工作。 

在這裏,我們構造了構造函數private- 這意味著類外的用戶不能直接創建實例。在我們的伴隨對象塊中,我們有壹個函數create(),它創建壹個Person對象並將其返回。 

調用伴隨對象函數

companion 對象實例化是懶惰的。換句話說,它只會在第壹次需要的時候被實例化。  companion 當companion 創建壹個類的實例或  companion 訪問對象成員時,就會發生對象  的實例化  。 

我們來看看如何在Kotlin中調用伴隨對象函數。

正如妳所看到的,這就像正常情況下在Java中調用靜態方法壹樣。換句話說,我們只是調用這個類然後調用成員。請註意,除了函數之外,我們還可以在伴隨對象中包含屬性。 

另請註意,companion類對其伴隨對象中聲明的所有屬性和函數進行了無限制的訪問,而伴隨對象無法訪問類成員。我們可以init在companion對象內部有壹個代碼塊 - 當創建伴隨對象時立即調用這個代碼塊。 

執行上面的代碼的結果將是:

請記住,只能有壹個類companion對象的單個實例存在。 

我們也可以自由地為我們的伴侶對象提供壹個名稱。

在這裏,我們給它起了壹個名字Factory。我們可以在Kotlin中這樣稱呼它:

這種風格是冗長的,所以堅持以前的方式更受歡迎。但是,當從Java調用伴隨對象函數或屬性時,這可能會派上用場。 

正如我前面所說,與對象壹樣,伴隨對象也可以包含屬性或函數,實現接口,甚至可以擴展壹個類。

在這裏,我們PersonFactory只有壹個create()功能的界面。看看我們新的修改後的  companion對象,它現在實現了這個接口(您將在後面的文章中了解Kotlin中的接口和繼承)。 

Java互操作性

在引擎蓋下,伴隨對象的編譯與Kotlin對象的編譯方式類似。在我們自己的案例中,為我們生成了兩個類:壹個最終Person類和壹個內部靜態最終類Person$Companion。 

Person類包含稱為最終靜態成員Companion-這個靜態字段是的壹個目的Person$Companion 內部類。該  Person$Companion 內部類也有自己的成員,其中壹人是被稱為公眾最終功能create()。 

請註意,我們沒有給我們的伴侶對象壹個名字,所以生成的靜態內部類是Companion。如果我們給了它壹個名字,那麽生成的名字就是我們在Kotlin中給出的名字。 

這裏,Kotlin中的伴隨對象沒有名稱,所以我們使用Companion編譯器為Java調用者提供的名稱來調用它。 

@JvmStatic應用於伴隨對象成員的註釋的工作方式與常規對象的工作方式類似。 

伴隨對象擴展 

與擴展函數如何擴展類的功能類似,我們也可以擴展伴隨對象的功能。(如果您想要復習Kotlin中的擴展函數,請參閱本系列中的高級函數教程)。 

在這裏,我們在伴隨對象ClassA.Companion上定義了壹個擴展函數extFunc()。換句話說,extfunc() 是對伴侶對象的擴展。 然後,我們可以調用擴展,就好像它是伴隨對象的成員函數(它不是!)。  

在幕後,編譯器將創建壹個靜態實用程序功能extFunc()。接收器對象作為該實用程序函數的參數  

結論

在本教程中,您了解了Kotlin中的基本類和對象。我們介紹了關於類的以下內容:

  • 類的創建
  • 構造方法
  • 屬性
  • 可見性修飾符
  • 智能casting
  • 顯式投射

此外,您還了解了Kotlin中的對象和伴隨對象如何輕松替換您在Java中編寫的靜態方法,常量和單例。 但那不是全部! 還有更多需要了解Kotlin的課程。在下壹篇文章中,我將向您展示Kotlin面向對象編程的更多精彩功能。再見! 

要了解有關Kotlin語言的更多信息,我建議訪問  Kotlin文檔。或者在Envato Tuts +上查看我們的其他壹些Android應用程序開發帖子! 

关注我们的公众号
Advertisement
Advertisement
Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.