为“数字类"重载+和+ =运算符 [英] overloading + and += operators for "Number Classes"
问题描述
我想为封装简单的Number
的类创建扩展功能.例如DoubleProperty
.我遇到了无法同时重载+
和+=
运算符的问题.
I want to create extension functions for classes that encapsulate simple Number
s. For example DoubleProperty
. I encountered the problem, that I can't overload the +
and the +=
operator at the same time.
我不会创建通过以下测试的行为:
I wan't to create a behaviour, that passes following tests:
class DoublePropertyTest {
lateinit var doubleProperty: DoubleProperty
@Before
fun initialize() {
doubleProperty = SimpleDoubleProperty(0.1)
}
@Test
fun plus() {
val someProperty = doubleProperty + 1.5
assertEquals(someProperty.value, 1.6, 0.001)
}
@Test
fun plusAssign() {
val someProperty = doubleProperty
doubleProperty += 1.5 //error if + and += are overloaded
assert(someProperty === doubleProperty) //fails with only + overloaded
assertEquals(doubleProperty.value, 1.6, 0.001)
}
}
可以使用以下扩展功能来实现:
It could be implemented using these extension functions:
operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty
= SimpleDoubleProperty(get() + number.toDouble())
operator fun WritableDoubleValue.plusAssign(number: Number)
= set(get() + number.toDouble())
问题是,如果+
被覆盖,则+=
也不能被重载:
The problem is, that if +
is overlodaded the +=
can't be overloaded aswell:
Assignment operators ambiguity. All these functions match.
- public operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty
- public operator fun WritableDoubleValue.plusAssign(number: Number): Unit
如果仅重载+
运算符,则在+=
操作上将返回一个新的DoubleProperty
对象,而不是初始对象.
If I only overload the +
operator, a new DoubleProperty
object is returned on +=
operations instead of the initial one.
有没有办法解决此限制?
Is there a way to work around this limitation?
推荐答案
科特林怪异的+=
运算符
您都可以在kotlin中重载plus
运算符和plusAssign
运算符,但是您必须遵循kotlin的规则来解决奇怪的+=
冲突.
The strange +=
operator in Kotlin
you can both overloading the plus
operator and plusAssign
operator in kotlin, but you must following the rules of kotlin to solving the strange +=
conflicts.
-
为
plus
运算符引入类的不可变结构,这意味着该类之外的任何类都无法编辑其内部数据.
introduce an immutable structure of the class for the
plus
operator which means any class outside the class can't edit its internal data.
为plusAssign
运算符引入类的可变结构,这意味着其内部数据可以在任何地方进行编辑.
introduce a mutable structure of the class for the plusAssign
operator which means its internal data can be edited anywhere.
kotlin已经在stdlib
中为Collection
& Map
类, MutableCollection#plusAssign 如下:
the kotlin has already done such things in the stdlib
for the Collection
& the Map
classes, the Collection#plus and MutableCollection#plusAssign as below:
operator fun <T> Collection<T>.plus(elements: Iterable<T>): List<T>
// ^--- immutable structure
operator fun <T> MutableCollection<in T>.plusAssign(elements: Iterable<T>)
// ^--- mutable structure
但是,等等,当我们使用+=
运算符时如何解决冲突?
IF 该列表是不可变的Collection
,然后必须定义一个可变的var
变量,然后使用plus
运算符,因为它的内部状态无法编辑.例如:
But wait, how to solving the conflict when we using the +=
operator?
IF the list is an immutable Collection
then you must define a mutable var
variable, then the plus
operator is used since its internal state can't be edited. for example:
// v--- define `list` with the immutable structure explicitly
var list: List<Int> = arrayListOf(1); //TODO: try change `var` to `val`
val addend = arrayListOf(2);
val snapshot = list;
list += addend;
// ^--- list = list.plus(addend);
// list = [1, 2], snapshot=[1], addend = [2]
如果,列表是可变的MutableCollection
,则必须定义一个不变的val
变量,然后使用plusAssign
运算符,因为它的内部状态可以在任何位置进行编辑.例如:
IF the list is a mutable MutableCollection
then you must define a immutable val
variable, then the plusAssign
operator is used since its internal state can be edited anywhere. for example:
// v--- `list` uses the mutable structure implicitly
val list = arrayListOf(1); //TODO: try change `val` to `var`
val addend = arrayListOf(2);
val snapshot = list;
list += addend;
// ^--- list.plusAssign(addend);
// list = [1, 2], snapshot=[1, 2], addend = [2]
另一方面,您可以为 operator 重载diff签名,每个签名用于不同的 context ,而kotlin也可以这样做,例如: Collection#plus .例如:
On the other hand, you can overloads an operator with diff signatures, each signature for the different context, and kotlin also do it, e.g: Collection#plus. for example:
var list = listOf<Int>();
list += 1; //list = [1];
// ^--- list = list.plus(Integer);
list += [2,3]; //list = [1, 2, 3]
// ^--- list = list.plus(Iterable);
这篇关于为“数字类"重载+和+ =运算符的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!