Java方法错误地获取自动重载科特林

问题描述:

鉴于含有下列(冷凝)类的Java库:Java方法错误地获取自动重载科特林

public class Vector2f { 
    public float x; 
    public float y; 

    public Vector2f div(Vector2f other) { 
     x /= other.x; 
     y /= other.y; 
     return this; 
    } 

    public Vector2f div(Vector2f other, Vector2f dest) { 
     dest.x = x/other.x; 
     dest.y = y/other.y; 
     return dest; 
    } 

    /* ... */ 
} 

由于自动地科特林合适方法名转换成重载操作,我可以写

val v0 = Vector2f(12f, 12f) 
val v1 = Vector2f(2f, 2f) 

val res = v0/v1 

println(v0) 
println(v1) 
println(res) 

res.x = 44f 
println() 

println(v0) 
println(v1) 
println(res) 

...与完全出乎意料的结果是v0得到由缀除法运算突变。并且此外,该参考存储在res指向相同的对象v0输出:

Vector2f(6.0, 6.0) 
Vector2f(2.0, 2.0) 
Vector2f(6.0, 6.0) 

Vector2f(44.0, 6.0) 
Vector2f(2.0, 2.0) 
Vector2f(44.0, 6.0) 

由于库还提供了一种过载写结果到另一个载体中,我想知道如果我不能告诉' kotlin不要使用提供的Vector2f.div(Vector2f)方法。

我已经尝试提供了一个扩展的方法来Vector2f但得到的真正的成员阴影:

operator fun Vector2f.div(other: Vector2f): Vector2f = this.div(other, Vector2f()) 
         ^~~ extension is shadowed by a member: public open operator fun div(other: Vector2f!): Vector2f! 
+1

如果有兴趣,请点击这里(https://github.com/elect86/glm)glm port – elect

+0

@选择使用你的端口是最好的解决方案,为什么你不作为回答发布? – voddan

+0

害怕出现太多坚持/侵入性,但既然你建议,我会试试.. – elect

理想情况下,你会改变的Java类,以使其操作功能遵守公约更好。如果您无法修改原始课程,那么您在使用Kotlin时始终可以使用/运营商。

因为它是原班里面,你将无法与扩展功能来覆盖它,原来总是优先于它,无论在哪里扩展声明,或者它如何进口。

你要么必须习惯于可用的语法,要么你真的不能拥有这些语法,你可以创建一个围绕Vector2f的包装类,它没有公开提供该名称的功能。

+0

这是一种悲伤,因为图书馆是非常好的。但使用运营商超载,完全令人惊讶,你是坏的:( – baeda

+0

'@ kotlin.internal.HidesMembers'会解决问题,但你知道,如果你为JetBrains工作.. – voddan

我的工作GLM端口here

。对于你的榜样,相关代码here

operator fun div(b: Float) = div(Vec2(), this, b, b) 
operator fun div(b: Vec2) = div(Vec2(), this, b.x, b.y) 

fun div(bX: Float, bY: Float, res: Vec2 = Vec2()) = div(res, this, bX, bY) 
fun div(b: Float, res: Vec2 = Vec2()) = div(res, this, b, b) 
fun div(b: Vec2, res: Vec2 = Vec2()) = div(res, this, b.x, b.y) 

fun div_(bX: Float, bY: Float) = div(this, this, bX, bY) 
infix fun div_(b: Float) = div(this, this, b, b) 
infix fun div_(b: Vec2) = div(this, this, b.x, b.y) 

背后的逻辑很简单,引用您的样品,最短/最简单的代码:

val v0 = Vec2(12f) 
val v1 = Vec2(2f) 

val res = v0/v1 

总是创建一个新的实例。这不知何故遵循也编写在Kotlin docs上的指导原则。以及目前仍然存在的inc()dec()部分(它在此期间被修改)。

而且是不易出错的形式尽可能(个人经验..)

对于性能的关键场景,当你不想分配一个新的实例,妥协是要放弃的操作符重载通过v1

v0.div(v1, res) 

这意味着,除v0和结果放在res:并使用函数形式。

如果您想接收对象变异,并直接容纳结果:

v0 div_ v1 

这背后的想法是利用相似下划线_和等号=后面解释div_/=

+0

我upvoted的努力,我敢肯定因为它没有提供问题的答案('我可以让kotlin接受我的运算符而不是自动生成的'),所以我不能接受你的GLM端口这是正确的,我很害怕! – baeda

+1

是啊,别担心,我完全理解它,谢谢你的提升:)我希望它对那些会遇到类似问题的人有用 – elect