Kotlin學習(十): 可見性修飾符和數據類

Interoperable

Java中有可見性修飾符(private…),而Kotlin中也是有這樣的修飾符,但也有一些不一樣,下面來學習Kotlin中的可見性修飾符(Visibility Modifiers)和數據類(Data Classes)的相關知識。

可見性修飾符(Visibility Modifiers)

Kotlin有四種可見性修飾符,分別是publicinternalprotectedprivate,默認的修飾符是public,除了internal之外,其他三種修飾符與Java的訪問權限一樣。

Kotlin的可見性除了用於類,對象,接口,構造函數,屬性之外,還用於屬性的setter方法(getter的可見性是由屬性的可見性決定的)。

屬性可見性修飾

// 文件名: example.kt
package foo

private fun foo() {} // 在example.kt中可見

public var bar: Int = 5 // 任何地方都可見
// 因爲get的可見性是由屬性決定的,所有這裏的get的可見性爲public
       private set // setter在example.kt中可見

internal val baz = 6 // 在模塊中可見

注意:protectedTop-level中不可以使用

private修飾的屬性是不會自動生成get和set方法的

在Kotlin中可以使用使用屬性名來直接獲取值和設置值的,原因就是Kotlin會自動生成屬性的getset方法

但是,如果如果設置屬性的可見性是private的話,我們知道private修飾的是私有的,也就是當前類可用,那麼就不會自動生成getset方法了,不能給外部訪問。

類和接口的可見性修飾

open class Outer {
    private val a = 1 // 在Outer類中可見
    protected open val b = 2 // 在Outer類和子類中可見
    internal val c = 3 // 在模塊中可見
    val d = 4  // 默認爲public

    protected class Nested {
        public val e: Int = 5
    }
}

class Subclass : Outer() {
    // a不可見
    // b,c和d可見
    // Nested類和e可見

    override val b = 5   // 重寫後的b依然是protected
}

class Unrelated(o: Outer) {
    // o.a和o.b不可見
    // o.d可見,在相同模塊下o.c可見
    // Outer.Nested不可見, Nested::e也是不可見
}

注意:外部類不可以訪問內部類的private成員。

構造函數同樣可以設置可見性,前面說過,在設置主構造函數的可見性或者註解的時候,要加上constructor關鍵字。

class C @Inject private constructor(a: Int) { ... }

Kotlin中局部變量,函數和類是不允許使用修飾符的。

模塊(Modules)

internal權限是是模塊級別的訪問權限,可以訪問本模塊的internal變量和方法,當跨模塊的時候就無法訪問另一個模塊的internal變量或方法。

數據類(Data Classes)

前面說過(Kotlin學習(五): 慣用語法和代碼風格),Kotlin的慣用語法是有寫POJO類,一般寫那種類都是用data修飾的類,也就是數據類表示,只保存數據的類。

data class User(val name: String, val age: Int)

編譯器自動從主構造函數中聲明的所有屬性生成以下方法

User類

可以看出有 gettersetter方法,還有componentN()函數,對應按聲明順序出現的所有屬性,如name就是component1()age就是component2()

當然還有 equals()hashCode()、和 toString()(輸出的格式爲User(name=..., age=...)),爲什麼生成的class文件中沒有這三個類,但是又可以直接調用呢?

Any類

Any類是Kotlin每個類的超類,所以自然可以調用這幾個方法。

爲了確保數據類生成的代碼的一致性和有意義,必須滿足
- 如果構造函數參數中沒有聲明是val或者var,這些函數就不會生成
- 主構造函數需要有至少一個參數
- 數據類不能有abstractopensealedinner修飾
- 在1.1版本之前,數據類只能實現接口

構造函數那裏也說過,如果生成的類需要一個無參數的構造函數,則必須指定所有屬性的默認值

data class User(var name: String = "", var age: Int = 0)

複製(copying)

數據類在創建的時候,除了會生成上面的幾個方法外,還會生成一個copy
()
函數,copy()能夠複製一個對象改變它的一些屬性情況下,又要保持其餘的不變,如上面的User類,copy()函數的實現:

fun copy(name: String = this.name, age: Int = this.age) = User(name, age)

copy

在使用copy()之後,就可以修改數據類的一些屬性了:

val jack = User(name = "jack", age = 1)
val olderJack = jack.copy(age = 2)

Kotlin提供了PairTriple作爲標準數據類,命名數據類是更好的設計選擇。
兩個參數的時候使用Pair數據類
Pair

三個參數的時候使用Triple數據類
Triple

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