Kotlin 属性 的私有 getter 和 public setter
Private getter and public setter for a Kotlin property
如何在 Kotlin 中创建一个具有私有 getter(或根本没有)但具有 public setter 的 属性?
var status
private get
不工作,出现错误:Getter visibility must be the same as property visibility
在我的例子中,原因是 Java 互操作:我希望我的 Java 代码能够调用 setStatus
但不能调用 getStatus
.
在当前的 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"
}
目前在 Kotlin 中不可能有 属性 和 setter 比 属性 更明显。问题跟踪器中存在语言设计问题,请随时 watch/vote 或分享您的用例:https://youtrack.jetbrains.com/issue/KT-3110
具有编译时错误的只写属性 可以 自 Kotlin 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
编译错误也很有帮助:
Using 'getter for property: Int' is an error. Property can only be written.
用例
主要用例显然是允许写入但不能读取属性的 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
一起使用。
如何在 Kotlin 中创建一个具有私有 getter(或根本没有)但具有 public setter 的 属性?
var status
private get
不工作,出现错误:Getter visibility must be the same as property visibility
在我的例子中,原因是 Java 互操作:我希望我的 Java 代码能够调用 setStatus
但不能调用 getStatus
.
在当前的 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"
}
目前在 Kotlin 中不可能有 属性 和 setter 比 属性 更明显。问题跟踪器中存在语言设计问题,请随时 watch/vote 或分享您的用例:https://youtrack.jetbrains.com/issue/KT-3110
具有编译时错误的只写属性 可以 自 Kotlin 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
编译错误也很有帮助:
Using 'getter for property: Int' is an error. Property can only be written.
用例
主要用例显然是允许写入但不能读取属性的 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
一起使用。