您的位置:首頁>正文

Kotlin 類和對象

類定義

Kotlin 類可以包含:構造函數和初始化代碼塊、函數、屬性、內部類、物件聲明。

Kotlin 中使用關鍵字 class 聲明類, 後面緊跟類名:

class Runoob { // 類名為 Runoob // 大括弧內是類體構成}

我們也可以定義一個空類:

class Empty

可以在類中定義成員函數:

class Runoob() { fun foo() { print("Foo") } // 成員函數}

類的屬性

屬性定義

類的屬性可以用關鍵字 var 聲明為可變的, 否則使用唯讀關鍵字 val 聲明為不可變。

class Runoob { var name: String = …… var url: String = …… var city: String = ……}

我們可以像使用普通函數那樣使用構造函數創建類實例:

val site = Runoob() // Kotlin 中沒有 new 關鍵字

要使用一個屬性, 只要用名稱引用它即可

site.name // 使用 . 號來引用site.url

Koltin 中的類可以有一個 主構造器, 以及一個或多個次構造器, 主構造器是類頭部的一部分,

位於類名稱之後:

class Person constructor(firstName: String) {}

如果主構造器沒有任何注解, 也沒有任何可見度修飾符, 那麼constructor關鍵字可以省略。

class Person(firstName: String) {}

getter 和 setter

屬性聲明的完整語法:

var [: ] [= ] [] []

getter 和 setter 都是可選

如果屬性類型可以從初始化語句或者類的成員函數中推斷出來, 那就可以省去類型, val不允許設置setter函數, 因為它是唯讀的。

var allByDefault: Int? // 錯誤: 需要一個初始化語句, 默認實現了 getter 和 setter 方法var initialized = 1 // 類型為 Int, 默認實現了 getter 和 setterval simple: Int? // 類型為 Int , 默認實現 getter , 但必須在構造函數中初始化val inferredType = 1 // 類型為 Int 類型,預設實現 getter

實例

以下實例定義了一個 Person 類, 包含兩個可變變數 lastName 和 no, lastName 修改了 getter 方法, no 修改了 setter 方法。

class Person { var lastName: String = "zhang" get() = field.toUpperCase() // 將變數賦值後轉換為大寫 set var no: Int = 100 get() = field // 後端變數 set(value) { if (value < 10) { // 如果傳入的值小於 10 返回該值 field = value } else { field = -1 // 如果傳入的值大於等於 10 返回 -1 } } var heiht: Float = 145.4f private set}// 測試fun main(args: Array) { var person: Person = Person() person.lastName = "wang" println("lastName:${person.lastName}") person.no = 9 println("no:${person.no}") person.no = 20 println("no:${person.no}")}

輸出結果為:

lastName:WANGno:9no:-1

Kotlin 中類不能有欄位。

提供了 Backing Fields(後端變數) 機制,備用欄位使用field關鍵字聲明,field 關鍵字只能用於屬性的訪問器, 如以上實例:

var no: Int = 100 get() = field // 後端變數 set(value) { if (value < 10) { // 如果傳入的值小於 10 返回該值 field = value } else { field = -1 // 如果傳入的值大於等於 10 返回 -1 } }

非空屬性必須在定義的時候初始化,kotlin提供了一種可以延遲初始化的方案,使用 lateinit 關鍵字描述屬性:

public class MyTest { lateinit var subject: TestSubject @SetUp fun setup() { subject = TestSubject() } @Test fun test() { subject.method() // dereference directly }}

主構造器

主構造器中不能包含任何代碼, 初始化代碼可以放在初始化程式碼片段中, 初始化程式碼片段使用 init 關鍵字作為首碼。

class Person constructor(firstName: String) { init { println("FirstName is $firstName") }}

注意:主構造器的參數可以在初始化程式碼片段中使用, 也可以在類主體n定義的屬性初始化代碼中使用。 一種簡潔語法, 可以通過主構造器來定義屬性並初始化屬性值(可以是var或val):

class People(val firstName: String, val lastName: String) { //...}

如果構造器有注解, 或者有可見度修飾符,

這時constructor關鍵字是必須的, 注解和修飾符要放在它之前。

實例

創建一個 Runoob類, 並通過構造函數傳入網站名:

class Runoob constructor(name: String) { // 類名為 Runoob // 大括弧內是類體構成 var url: String = "http://www.runoob.com" var country: String = "CN" var siteName = name init { println("初始化網站名: ${name}") } fun printTest() { println("我是類的函數") }}fun main(args: Array) { val runoob = Runoob("菜鳥教程") println(runoob.siteName) println(runoob.url) println(runoob.country) runoob.printTest()}

輸出結果為:

初始化網站名: 菜鳥教程菜鳥教程http://www.runoob.comCN我是類的函數

次構造函數

類也可以有二級構造函數, 需要加首碼 constructor:

class Person { constructor(parent: Person) { parent.children.add(this) }}

如果類有主構造函數, 每個次構造函數都要, 或直接或間接通過另一個次構造函數代理主構造函數。 在同一個類中代理另一個構造函數使用 this 關鍵字:

class Person(val name: String) { constructor (name: String, age:Int) : this(name) { // 初始化... }}

如果一個非抽象類別沒有聲明構造函數(主構造函數或次構造函數), 它會產生一個沒有參數的構造函數。 構造函數是 public 。 如果你不想你的類有公共的構造函數, 你就得聲明一個空的主構造函數:

class DontCreateMe private constructor () {}

注意:在 JVM 虛擬機器中, 如果主構造函數的所有參數都有預設值, 編譯器會生成一個附加的無參的構造函數, 這個構造函數會直接使用預設值。 這使得 Kotlin 可以更簡單的使用像 Jackson 或者 JPA 這樣使用無參構造函數來創建類實例的庫。

class Customer(val customerName: String = "")

實例

class Runoob constructor(name: String) { // 類名為 Runoob // 大括弧內是類體構成 var url: String = "http://www.runoob.com" var country: String = "CN" var siteName = name init { println("初始化網站名: ${name}") } // 次構造函數 constructor (name: String, alexa: Int) : this(name) { println("Alexa 排名 $alexa") } fun printTest() { println("我是類的函數") }}fun main(args: Array) { val runoob = Runoob("菜鳥教程", 10000) println(runoob.siteName) println(runoob.url) println(runoob.country) runoob.printTest()}

輸出結果為:

初始化網站名: 菜鳥教程Alexa 排名 10000菜鳥教程http://www.runoob.comCN我是類的函數

抽象類別

抽象是物件導向程式設計的特徵之一, 類本身, 或類中的部分成員, 都可以聲明為abstract的。 抽象成員在類中不存在具體的實現。

注意:無需對抽象類別或抽象成員標注open注解。

open class Base { open fun f() {}}abstract class Derived : Base() { override abstract fun f()}

嵌套類

我們可以把類嵌套在其他類中, 看以下實例:

class Outer { // 外部類 private val bar: Int = 1 class Nested { // 嵌套類 fun foo() = 2 }}fun main(args: Array) { val demo = Outer.Nested().foo() // 調用格式:外部類.嵌套類.嵌套類方法/屬性 println(demo) // == 2}

內部類

內部類使用 inner 關鍵字來表示。

內部類會帶有一個對外部類的物件的引用, 所以內部類可以訪問外部類成員屬性和成員函數。

class Outer { private val bar: Int = 1 var v = "成員屬性" /**嵌套內部類**/ inner class Inner { fun foo() = bar // 訪問外部類成員 fun innerTest() { var o = this@Outer //獲取外部類的成員變數 println("內部類可以引用外部類的成員, 例如:" + o.v) } }}fun main(args: Array) { val demo = Outer().Inner().foo() println(demo) // 1 val demo2 = Outer().Inner().innerTest() println(demo2) // 內部類可以引用外部類的成員, 例如:成員屬性}

為了消除歧義, 要訪問來自外部作用域的 this, 我們使用this@label, 其中 @label 是一個 代指 this 來源的標籤。

匿名內部類

使用物件運算式來創建匿名內部類:

class Test { var v = "成員屬性" fun setInterFace(test: TestInterFace) { test.test() }}/*** 定義介面*/interface TestInterFace { fun test()}fun main(args: Array) { var test = Test() /** * 採用物件運算式來創建介面物件, 即匿名內部類的實例。 */ test.setInterFace(object : TestInterFace { override fun test() { println("物件運算式創建匿名內部類的實例") } })}

類的修飾符

類的修飾符包括 classModifier 和_accessModifier_:

classModifier: 類屬性修飾符, 標示類本身特性。

abstract // 抽象類別 final // 類不可繼承,預設屬性enum // 枚舉類open // 類可繼承,類默認是final的annotation // 注解類

accessModifier: 存取權限修飾符

private // 僅在同一個文件中可見protected // 同一個檔中或子類可見public // 所有調用的地方都可見internal // 同一個模組中可見

實例

// 檔案名:example.ktpackage fooprivate fun foo() {} // 在 example.kt 內可見public var bar: Int = 5 // 該屬性隨處可見internal val baz = 6 // 相同模組內可見

標示類本身特性。

abstract // 抽象類別 final // 類不可繼承,預設屬性enum // 枚舉類open // 類可繼承,類默認是final的annotation // 注解類

accessModifier: 存取權限修飾符

private // 僅在同一個文件中可見protected // 同一個檔中或子類可見public // 所有調用的地方都可見internal // 同一個模組中可見

實例

// 檔案名:example.ktpackage fooprivate fun foo() {} // 在 example.kt 內可見public var bar: Int = 5 // 該屬性隨處可見internal val baz = 6 // 相同模組內可見

同類文章
Next Article
喜欢就按个赞吧!!!
点击关闭提示