[英]Private getter and public setter for a Kotlin property
How to make a property in Kotlin that has a private getter (or just do not have it) but has a public setter?如何在 Kotlin 中创建具有私有 getter(或只是没有)但具有公共 setter 的属性?
var status
private get
doesn't work with an error: Getter visibility must be the same as property visibility
不会出现错误:
Getter visibility must be the same as property visibility
In my case, the reason is for Java interop: I want my Java code to be able to call setStatus
but not getStatus
.就我而言,原因是 Java 互操作:我希望我的 Java 代码能够调用
setStatus
而不是getStatus
。
It's impossible at the moment in Kotlin to have a property with a setter that is more visible than the property.目前在 Kotlin 中不可能有一个属性的 setter 比属性更明显。 There's a language design issue in the issue tracker on this, feel free to watch/vote for it or share your use cases: https://youtrack.jetbrains.com/issue/KT-3110
问题跟踪器中存在一个语言设计问题,请随时观看/投票或分享您的用例: https : //youtrack.jetbrains.com/issue/KT-3110
In current Kotlin version (1.0.3) the only option is to have separate setter method like so:在当前的 Kotlin 版本 (1.0.3) 中,唯一的选择是使用单独的setter方法,如下所示:
class Test {
private var name: String = "name"
fun setName(name: String) {
this.name = name
}
}
If you wish to restrict external libraries from accessing the getter you can useinternal
visibility modifier allowing you to still use property syntax within the library:如果您希望限制外部库访问 getter,您可以使用
internal
可见性修饰符,允许您仍然在库中使用属性语法:
class Test {
internal var name: String = "name"
fun setName(name: String) { this.name = name }
}
fun usage(){
val t = Test()
t.name = "New"
}
Write-only properties with compile-time errors can be achieved since Kotlin 1.0, using a workaround based on @Deprecated
.编译时错误只写属性可以自科特林1.0来实现,使用基于一种变通方法
@Deprecated
。
Kotlin allows to mark functions deprecated with level ERROR
, which leads to a compile-time error when called. Kotlin 允许使用
ERROR
级别标记已弃用的函数,这会在调用时导致编译时错误。 Annotating the get
accessor of a property as error-deprecated , combined with a backing field (so that private reads are still possible), achieves the desired behavior:将属性的
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
}
Usage:用法:
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
The compile error is quite helpful, too:编译错误也很有帮助:
Using 'getter for property: Int' is an error.
使用 'getter for property: Int' 是一个错误。 Property can only be written.
属性只能写。
The main use case are obviously APIs that allow properties to be written, but not read:主要用例显然是允许写入但不允许读取属性的 API:
user.password = "secret" val pw = user.password // forbidden
Another scenario is a property which modifies the internal state, but is not stored itself as a field.另一种情况是修改内部状态的属性,但它本身不作为字段存储。 (Could be done more elegantly using different design).
(可以使用不同的设计更优雅地完成)。
body.thrust_force = velocity body.gravity_force = Vector(0, 0, 9.8) // only total force accessible, component vectors are lost val f = body.forces
This pattern is also useful for DSLs of the following kind:此模式对于以下类型的 DSL 也很有用:
server { port = 80 host = "www.example.com" }
In such cases, values are simply used as one-time settings, and the write-only mechanism described here can prevent accidentally reading a property (which might not be initialized yet).在这种情况下,值仅用作一次性设置,此处描述的只写机制可以防止意外读取属性(可能尚未初始化)。
Since this feature was not designed for this use case, it comes with certain limitations:由于此功能不是为此用例设计的,因此具有某些限制:
If accessed using a property reference, the compile-time error turns into a runtime error:如果使用属性引用访问,编译时错误会变成运行时错误:
val ref = wo::property val x = ref.get() // throws NotImplementedError
The same is true for reflection.反射也是如此。
This functionality cannot be outsourced into a delegate, because an error-deprecated getValue()
method cannot be used with by
.此功能不能外包给委托,因为错误弃用的
getValue()
方法不能与by
一起使用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.