当前位置: 首页 > 知识库问答 >
问题:

Kotlin属性的私有getter和公共setter

宋瀚海
2023-03-14

如何在Kotlin中创建一个具有私有getter(或只是没有)但具有公共setter的属性?

var status
private get

不能使用错误:getter可见性必须与属性可见性相同

在我的例子中,原因是Java Interop:我希望我的Java代码能够调用setstatus,但不能调用getstatus

共有1个答案

强承望
2023-03-14

自Kotlin1.0以来,可以使用基于@deprecated的解决方案来实现带有编译时错误的只写属性。

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

>

  • 主要用例显然是允许写属性但不允许读属性的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
    

  •  类似资料:
    • 我对Kotlin很陌生,并试图将一个项目从Java迁移到它。我对Kotlin的属性和它们的getters/setter以及可见性范围有点困惑。 我想要实现的是: 所以基本上我需要创建一个具有私有属性的类。此属性应由公共 getter 访问,但它不应具有 setter。此外,此属性应该是内部可变的,以便可以使用某种方法(如 更改其值。 据我所知,我不能将其声明为,因为在这种情况下,它将是完全不可变的

    • 如何使用自定义setter声明属性,但在Kotlin中没有getter?例如,在安科,他们这样做: 但在我看来,这有点骇人。这样做对吗?如果是,那么当一个项目没有Anko依赖关系时,情况会怎样呢? 附言:让我说清楚——我想没有吸气剂,而不是私人吸气剂

    • 在私有类中创建一个全局List并具有getter和setter方法会更好,还是只公开它会更好?Java的标准是什么? 我被教导将变量设为私有,只有getter和setter方法,但是访问公共列表肯定比私有列表更好。 这是我的观点,但我当然更喜欢按照标准去做,而不是按照看起来好的去做。

    • 如果你的javascript语言基础还可以,应该明白类、基类、子类、父类等概念。如果你有这些类的概念,那么在学习Threejs的过程中,如何查找Threejs文档将会比较顺利。 点材质PointsMaterial、基础线材质LineBasicMaterial、基础网格材质MeshBasicMaterial、高光网格材质MeshPhongMaterial等材质都是父类Material的子类。 各种各

    • 我有一个基类,它使用php魔术方法__get和__set,可以修改扩展类中的私有属性。然后,我为相关的私有属性构建setter getter函数(类似于http://www.beaconfire-red.com/epic-stufle/better-getters-and-setters-php)

    • 我希望我的类有一个字段,该字段返回所有公共访问的不可变列表,但在对象实例中,我希望列表是可变的,以便我可以向其添加元素。 我试过了,但不确定这是否被视为良好做法?