簡體   English   中英

Kotlin 屬性的私有 getter 和公共 setter

[英]Private getter and public setter for a Kotlin property

如何在 Kotlin 中創建具有私有 getter(或只是沒有)但具有公共 setter 的屬性?

var status
private get

不會出現錯誤: Getter visibility must be the same as property visibility

就我而言,原因是 Java 互操作:我希望我的 Java 代碼能夠調用setStatus而不是getStatus

目前在 Kotlin 中不可能有一個屬性的 setter 比屬性更明顯。 問題跟蹤器中存在一個語言設計問題,請隨時觀看/投票或分享您的用例: https : //youtrack.jetbrains.com/issue/KT-3110

在當前的 Kotlin 版本 (1.0.3) 中,唯一的選擇是使用單獨的setter方法,如下所示:

class Test {
    private var name: String = "name"

    fun setName(name: String) {
        this.name = name
    }
}

如果您希望限制外部庫訪問 getter,您可以使用internal可見性修飾符,允許您仍然在庫中使用屬性語法:

class Test {
    internal var name: String = "name"
    fun setName(name: String) { this.name = name }
}

fun usage(){
    val t = Test()
    t.name = "New"
}

編譯時錯誤只寫屬性可以自科特林1.0來實現,使用基於一種變通方法@Deprecated

實施

Kotlin 允許使用ERROR級別標記已棄用的函數,這會在調用時導致編譯時錯誤。 將屬性的get訪問器注釋為error-deprecated ,結合支持字段(以便私有讀取仍然可能),實現了所需的行為:

class WriteOnly {
    private var backing: Int = 0

    var property: Int
        @Deprecated("Property can only be written.", level = DeprecationLevel.ERROR)
        get() = throw NotImplementedError()
        set(value) { backing = value }

    val exposed get() = backing // public API
}

用法:

val wo = WriteOnly()
wo.property = 20         // write: OK

val i: Int = wo.property // read: compile error
val j: Int = wo.exposed  // read value through other property

編譯錯誤也很有幫助:

使用 'getter for property: Int' 是一個錯誤。 屬性只能寫。


用例

  1. 主要用例顯然是允許寫入但不允許讀取屬性的 API:

     user.password = "secret" val pw = user.password // forbidden
  2. 另一種情況是修改內部狀態的屬性,但它本身不作為字段存儲。 (可以使用不同的設計更優雅地完成)。

     body.thrust_force = velocity body.gravity_force = Vector(0, 0, 9.8) // only total force accessible, component vectors are lost val f = body.forces
  3. 此模式對於以下類型的 DSL 也很有用:

     server { port = 80 host = "www.example.com" }

    在這種情況下,值僅用作一次性設置,此處描述的只寫機制可以防止意外讀取屬性(可能尚未初始化)。


限制

由於此功能不是為此用例設計的,因此具有某些限制:

  • 如果使用屬性引用訪問,編譯時錯誤會變成運行時錯誤:

     val ref = wo::property val x = ref.get() // throws NotImplementedError
  • 反射也是如此。

  • 此功能不能外包給委托,因為錯誤棄用的getValue()方法不能與by一起使用。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM