目前我有abstract class:
abstract class Vec2t<T : Number> {
abstract var x: T
abstract var y: T
...
}
以及许多实施方案,例如this one:
data class Vec2(override var x: Float, override var y: Float) : Vec2t<Float>()
现在,我希望在Java中具有与Kotlin相同的访问行为,即:
val f = v.x
或
v.x = f
但当然来自Java,默认是:
float f = v.getX();
或
v.setX(f);
我以某种方式减少了压力&#34;通过编写具体的access funtions:
fun x(x: T) {
this.x = x
}
fun y(y: T) {
this.y = y
}
所以我只能&#34;
:float f = v.x();
或
v.x(f);
但是,如果我能像Kotlin那样拥有那些,我真的很喜欢:
float f = v.x;
或
v.x = f;
问题是@JvmField
属性不允许abstract
,但如果我将Vec2t
切换为:
open class Vec2t<T : Number> {
@JvmFiled open var x: T // error
属性必须初始化或抽象
@JvmField open var x by Delegates.notNull<T>()
无效:
@JvmField无法应用于委托属性
如果我尝试初始化它:
@JvmField open var x = 0 as T
@JvmField只能应用于最终属性
我有机会不知道吗?
答案 0 :(得分:2)
由于在Java中直接访问@JvmField
,我们无法像委托那样使用任何棘手的东西进行初始化,也不能将其标记为lateinit
。这也是它不能由抽象或开放财产支持的原因;如果你在Java中的一个类中有float x;
,它可以直接访问,并且你不能以任何方式拦截对它的读/写,这需要上述所有功能。
您尝试解决的问题是在创建时使用有效值初始化它们。你可以做的一件事是将它们标记为可空并将它们初始化为null
,但我认为这会直接影响你正在寻找的便利性(可能是性能,因为它们现在必须被装箱) ,我以为我会提到它是可能的。
所有这一切要说的是你基本上坚持使用你的一个解决方案,或者如果它适合你的用例,我建议从构造函数参数初始化它们:
abstract class Vec2t<T : Number> constructor(_x: T, _y: T) {
@JvmField
var x: T = _x
@JvmField
var y: T = _y
}
class Vec2(x: Float, y: Float) : Vec2t<Float>(x, y)
通过这种方式,您可以将您的值标记为@JvmField
,并且可以直接从两种语言访问它们,并且它们在创建时具有真正的价值。
<强>更新强>
这是一个较短的版本(@mfulton26):
abstract class Vec2t<T : Number>(@JvmField var x: T, @JvmField var y: T)
答案 1 :(得分:-1)
@JvmField指示Kotlin编译器不为此属性生成getter / setter并将其作为字段公开,因此如果它是一个字段,则无法覆盖它。
对于你的情况,你需要这样的东西:
CountRequestBuilder