首页 文章

Kotlin酒店的私人吸气剂和公共二传手

提问于
浏览
30

如何在Kotlin建造一个拥有私人吸气剂(或者只是没有它)但拥有公共二传手的 properties ?

var status
private get

不适用于错误: Getter visibility must be the same as property visibility

就我而言,原因是Java互操作:我希望我的Java代码能够调用 setStatus 而不是 getStatus .

3 回答

  • 22

    它是问题跟踪器中的语言设计问题,随时观看/投票或分享您的用例:https://youtrack.jetbrains.com/issue/KT-3110

  • 25

    在当前的Kotlin版本(1.0.3)中,唯一的选择是使用单独的setter方法,如下所示:

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

    如果您希望限制外部库访问getter,您可以使用internal visibility modifier,允许您仍然使用库中的属性语法:

    class Test {
        internal var name: String = "name"
        fun setName(name: String) { this.name = name }
    }
    
    fun usage(){
        val t = Test()
        t.name = "New"
    }
    
  • 0

    自Kotlin 1.0以来,使用基于 @Deprecated 的变通方法实现了具有编译时错误的只写属性 can .

    实施

    Kotlin允许使用级别 ERROR 标记已弃用的函数,这会在调用时导致编译时错误 . 将属性的 get 访问器注释为错误弃用,并结合支持字段(以便仍可以进行私有读取),实现所需的行为:

    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'是一个错误 . property 只能写 .


    用例

    • 主要用例显然是允许写入属性但不读取的API:
    user.password = "secret"
    val pw = user.password // forbidden
    
    • 另一种情况是修改内部状态的属性,但不将其自身存储为字段 . (可以使用不同的设计更优雅地完成) .
    body.thrust_force = velocity
    body.gravity_force = Vector(0, 0, 9.8)
    // only total force accessible, component vectors are lost
    val f = body.forces
    
    • 此模式对于以下类型的DSL也很有用:
    server {
        port = 80
        host = "www.example.com"
    }
    

    在这种情况下,值只是用作一次性设置,此处描述的只写机制可以防止意外读取属性(可能尚未初始化) .


    限制

    由于此功能不是针对此用例设计的,因此它具有某些限制:

    • 如果使用属性引用访问,则编译时错误将变为运行时错误:
    val ref = wo::property
    val x = ref.get() // throws NotImplementedError
    
    • 反思也是如此 .

    • 此功能无法外包到委托中,因为错误弃用的 getValue() 方法不能与 by 一起使用 .

相关问题