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!
答
理想情况下,你会改变的Java类,以使其操作功能遵守公约更好。如果您无法修改原始课程,那么您在使用Kotlin时始终可以使用/
运营商。
因为它是原班里面,你将无法与扩展功能来覆盖它,原来总是优先于它,无论在哪里扩展声明,或者它如何进口。
你要么必须习惯于可用的语法,要么你真的不能拥有这些语法,你可以创建一个围绕Vector2f
的包装类,它没有公开提供该名称的功能。
答
我的工作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_
为/=
如果有兴趣,请点击这里(https://github.com/elect86/glm)glm port – elect
@选择使用你的端口是最好的解决方案,为什么你不作为回答发布? – voddan
害怕出现太多坚持/侵入性,但既然你建议,我会试试.. – elect