为“数字类"重载+和+ =运算符 [英] overloading + and += operators for "Number Classes"

查看:170
本文介绍了为“数字类"重载+和+ =运算符的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想为封装简单的Number的类创建扩展功能.例如DoubleProperty.我遇到了无法同时重载++=运算符的问题.

I want to create extension functions for classes that encapsulate simple Numbers. 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.

  1. plus运算符引入类的不可变结构,这意味着该类之外的任何类都无法编辑其内部数据.

  1. 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类,

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆