@JvmField en properties para una class genérica / abstracta

Por el momento tengo una class abstracta :

abstract class Vec2t<T : Number> { abstract var x: T abstract var y: T ... } 

y muchos implementadores, como este :

 data class Vec2(override var x: Float, override var y: Float) : Vec2t<Float>() 

Ahora, mi deseo era tener el mismo comportamiento de acceso que Kotlin en Java, es decir:

 val f = vx 

o

 vx = f 

pero, por supuesto, desde Java, el valor pnetworkingeterminado era:

 float f = v.getX(); 

o

 v.setX(f); 

Reduje de alguna manera la "presión" al escribir funciones de acceso específicas:

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

para que pueda "solo":

 float f = vx(); 

o

 vx(f); 

Pero aún así, realmente me encantaría si pudiera tenerlos como en Kotlin:

 float f = vx; 

o

 vx = f; 

El problema es que @JvmField no está permitido en las properties abstract , pero si cambio Vec2t a:

 open class Vec2t<T : Number> { @JvmFiled open var x: T // error 

la propiedad debe ser inicializada o abstracta

  @JvmField open var x by Delegates.notNull<T>() 

no es válido ni:

@JvmField no se puede aplicar para delegar properties

si intenté inicializarlo:

  @JvmField open var x = 0 as T 

@JvmField solo se puede aplicar a las properties finales

¿Hay alguna posibilidad para mí de la que no tengo conocimiento?

Como se accede a @JvmField directamente en Java, no podemos inicializar con nada complicado como un delegado, y tampoco podemos marcarlo como lateinit . Esta es también la razón por la cual no puede ser respaldada por una propiedad abstracta o abierta; si tienes float x; dentro de una class en Java, se accede directamente, y no se pueden interceptar las lecturas / escrituras de ninguna manera, lo que requeriría todas las características anteriores.

El problema que estás tratando de resolver es inicializarlos con valores válidos en la creación. Una cosa que podrías hacer es marcarlos como nulables e intializarlos como null , pero creo que eso iría directamente en contra de la conveniencia que estás buscando (y probablemente el performance, ya que ahora tendrían que estar encuadrados), solo pensé Mencionaría que es posible.

Todo esto para decir es que básicamente estás atrapado con una de tus soluciones, o si se adapta a tu caso de uso, te sugiero que las utilices desde los parameters del constructor:

 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) 

De esta manera, tiene sus valores marcados como @JvmField s y puede acceder directamente desde ambos idiomas, y se inicializan con un valor real en la creación.

Actualizar:

Aquí hay una versión más corta (por @ mfulton26 ):

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

@JvmField instruye al comstackdor de Kotlin para que no genere getters / setters para esta propiedad y lo exponga como un campo, por lo que si es un campo, no será posible sobrescribirlo.

Para su caso necesita algo como esto:

 abstract class Vec2t<T : Number> { @JvmField var x: T @JvmField var y: T } 
  • Java Lambda para Kotlin
  • Kotlin: ¿Cómo obtengo caracteres después de "@" en una cadena?
  • SonarQube: Android no funciona para gradle 3.0.0
  • ¿Cómo puedo verificar el tipo genérico en Kotlin?
  • Kotlin - Sort MutableList basado en Object Property
  • ¿Cómo puedo asignar un valor al parámetro KMutableProperty?
  • Error de configuration de Kotlin
  • Cómo pasar la class Java a la class de datos de Kotlin
  • Función de extensión en el enumerador, `values ​​()` no disponible?
  • Comstack Kotlin con una dependencia de jar desde una línea de command
  • Cómo crear una secuencia infinitamente larga en Kotlin