2017-03-07 85 views
1

目前性能我有一个​​3210:@JvmField对通用/抽象类

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); 

我莫名其妙地减少了 “压力” 通过编写特定access funtions

fun x(x: T) { 
    this.x = x 
} 
fun y(y: T) { 
    this.y = y 
} 

所以我可以“只”:

float f = v.x(); 

v.x(f); 

但是,我真的很喜欢,如果我能有那些在科特林:

float f = v.x; 

v.x = f; 

的问题是@JvmField不允许abstract和性能,但如果切换Vec2t到:

open class Vec2t<T : Number> { 

    @JvmFiled open var x: T // error 

属性必须被初始化或抽象

​​

无效既不:

@JvmField不能应用于委托物业

,如果我试图将其初始化:

@JvmField open var x = 0 as T 

@JvmField只能被应用到最终性能

有我一个机会,我不知道的?

回答

2

作为@JvmField是用Java直接访问,我们不能耍花样像一个委托初始化,并且不能将其标记为lateinit要么。这也是为什么它不能得到抽象或开放财产的支持;如果您在Java的类中有float x;,那么它可以直接访问,并且不能以任何方式拦截对其的读/写,而所有上述功能都需要。

你试图解决的问题是关于创造有效的值初始化它们。有一两件事你可以做的是将它们标记为可为空和intialize他们作为null,但我认为这将直接违背你正在寻找的便利性(可能的表现,因为他们会现在已经被盒装),我只是想我会提到这是可能的。

这一切说的是,你基本上是坚持你的解决方案之一,或者它是否适合你的使用情况,我建议从构造函数的参数intializing他们:

​​

这种方式你您的价值标记为@JvmField s,并且可以直接从两种语言访问它们,并且它们在创建时具有真正的价值。

更新:

下面是一个较短的版本(由@mfulton26):

abstract class Vec2t<T : Number>(@JvmField var x: T, @JvmField var y: T) 
+0

谢谢zsmb,它看起来很完美! – elect

+1

这'Vec2t'实现可以通过将被简化了'@ JvmField'属性直到构造:'抽象类Vec2t (@JvmField VAR X:T,@JvmField VAR Y:T)'。 – mfulton26

+0

哦,对,我不知道为什么我没有这样做,这很整洁。固定在让我们猜想他们在班级体内。 – zsmb13

0

@JvmField指示Kotlin编译器不要为此属性生成getters/setter,并将其作为字段公开,因此如果它是字段,将无法覆盖它。

对于你的情况,你需要这样的事:

abstract class Vec2t<T : Number> { 
    @JvmField 
    var x: T 

    @JvmField 
    var y: T 
} 
+0

>属性必须被初始化或抽象 – elect