Методы 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; } /* ... */ } 

Поскольку 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) , 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) , 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 мутируется операцией деления infix. И, кроме того, ссылка, сохраненная в res указывает на тот же объект, что и v0 Output:

 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 но он получает 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-портом здесь

Для вашего примера, соответствующий код здесь

 operator fun div(b: Float) = div(Vec2(), this, b, b) operator fun div(b: Vec2) = div(Vec2(), this, bx, by) 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, bx, by) 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, bx, by) 

Логика позади довольно проста, ссылаясь на ваш образец, самый короткий / самый простой код:

 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_ как /=

Intereting Posts
Проблемы с HasSupportFragmentInjector в kotlin – DispatchingAndroidInjector – null OnClickItemListener в spinner в андроиде просмотра recycler В TornadoFX, как я могу привязать свойства BigDecimal к другому свойству BigDecimal с помощью objectBinding? Android всех видов ошибок от Gradle и Kotlin Создать класс расширить AsyncTask без утечки контекстного объекта в Android Kotlin Как сохранить уведомление при исчезновении приложения? Утечка памяти активности Kotlin Методы Java ошибочно автоматически перегружаются в котлин Android N Java 8 (компилятор Jack) и Kotlin interop Сплит-алгоритм и часть просмотра с использованием шаблона стратегии в Котлине В TornadoFX, как я могу выбрать глубоко вложенное свойство для свойства nullable ItemViewModel? Kotlin: Интерфейс с неизменяемым свойством, реализуемым классом с изменчивым Диапазоны в Котлине ниже API 21 Ошибка или функция: Kotlin позволяет изменить «val» на «var» в наследовании Varargs Kotlin Java interop не работает должным образом