Java方法在kotlin中被错误地自动重载
给定包含以下(压缩)类的Java库: 由于kotlin自动将合适的方法名转换为重载运算符,因此我可以编写Java方法在kotlin中被错误地自动重载,java,operator-overloading,interop,kotlin,Java,Operator Overloading,Interop,Kotlin,给定包含以下(压缩)类的Java库: 由于kotlin自动将合适的方法名转换为重载运算符,因此我可以编写 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被中缀除法操作变异。
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端口
对于您的示例,相关代码是
背后的逻辑非常简单,参考您的示例,最短/最简单的代码:
val v0 = Vec2(12f)
val v1 = Vec2(2f)
val res = v0 / v1
始终创建一个新实例。这在某种程度上遵循了也写在地图上的指南。在inc()
和dec()
部分中仍然存在这些内容(同时已对其进行了修改)
也是尽可能不容易出错的表单(个人经验…)
对于性能关键的场景,当您不想分配新实例时,折衷方法是放弃运算符重载并使用函数形式:
v0.div(v1, res)
也就是说,将v0
除以v1
,并将结果放入res
如果希望接收者对象发生变异并直接适应结果:
v0 div_ v1
这背后的想法是利用下划线
和等号=
之间的相似性,并将div
解释为/=
如果有兴趣,glmport@elect使用你的端口是最好的解决方案,为什么你不发布一个答案呢?害怕显得太坚持/侵犯,但是既然你建议了,我就试试……这有点悲哀,因为图书馆真的很好。但是使用一个完全出乎你意料的操作符重载是不好的:(@kotlin.internal.HidesMembers
可以解决问题,但是你知道,如果你为JetBrains工作……我对这项工作投了更高的票,我肯定会查看你的GLM端口,而不是使用我现在拥有的端口。因为它没有提供问题的答案(‘我能让kotlin接受我的操作符重载而不是自动生成的重载吗’)真的,我恐怕不能接受它是正确的!是的,别担心,我完全明白,谢谢你的投票:)我希望它对那些和你有类似问题的人有用
v0.div(v1, res)
v0 div_ v1