繁体   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