Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/kotlin/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Operator overloading 超载+;和+;=运营商;“数字类”;_Operator Overloading_Kotlin_Extension Function - Fatal编程技术网

Operator overloading 超载+;和+;=运营商;“数字类”;

Operator overloading 超载+;和+;=运营商;“数字类”;,operator-overloading,kotlin,extension-function,Operator Overloading,Kotlin,Extension Function,我想为封装simpleNumbers的类创建扩展函数。例如DoubleProperty。我遇到的问题是,我不能同时重载+和+=操作符 我不想创建通过以下测试的行为: class DoublePropertyTest { lateinit var doubleProperty: DoubleProperty @Before fun initialize() { doubleProperty = SimpleDoubleProperty(0.1) }

我想为封装simple
Number
s的类创建扩展函数。例如
DoubleProperty
。我遇到的问题是,我不能同时重载
+
+=
操作符

我不想创建通过以下测试的行为:

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)
    }
}
可以使用以下扩展功能来实现:

operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty 
    = SimpleDoubleProperty(get() + number.toDouble())

operator fun WritableDoubleValue.plusAssign(number: Number) 
    = set(get() + number.toDouble())
问题是,如果
+
过负荷,那么
+=
也不能过载:

Assignment operators ambiguity. All these functions match.
- public operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty
- public operator fun WritableDoubleValue.plusAssign(number: Number): Unit
如果我只重载
+
操作符,则在
+=
操作上返回一个新的
DoubleProperty
对象,而不是初始对象


有没有办法绕过这个限制?

如果您的类是
DoubleProperty
,您可以将
plus
plusaSign
作为其方法,以解决任何歧义。

您不能同时重载
+
+=
。使其中一个过载

当您在代码中写入+=时,理论上,两者都加上plusaSign函数 可以调用(见图7.2)。如果是这种情况,并且两个函数都已定义和 如果适用,编译器将报告错误

我从《科特林在行动》一书中复制/粘贴

Kotlin中奇怪的
+=
运算符 您可以在kotlin中重载
plus
运算符和
plusaSign
运算符,但必须遵循kotlin的规则来解决奇怪的
+=
冲突

  • plus
    操作符引入类的不可变结构,这意味着类之外的任何类都不能编辑其内部数据

  • plusAssign
    运算符引入类的可变结构,这意味着其内部数据可以在任何地方编辑

  • kotlin已经在
    stdlib
    中为
    集合
    映射
    类做了如下工作:

    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
    
    如果列表是可变的
    MutableCollection
    ,则必须定义一个不可变的
    val
    变量,然后使用
    plusAssign
    运算符,因为其内部状态可以在任何地方编辑。例如:

    //         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]
    
    //    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]
    
    var list = listOf<Int>();
    
    list += 1; //list = [1];
    //   ^--- list = list.plus(Integer);
    
    list += [2,3]; //list = [1, 2, 3]
    //   ^--- list = list.plus(Iterable);
    
    另一方面,您可以使用不同的签名重载运算符,每个签名用于不同的上下文,kotlin也可以这样做,例如:。例如:

    //         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]
    
    //    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]
    
    var list = listOf<Int>();
    
    list += 1; //list = [1];
    //   ^--- list = list.plus(Integer);
    
    list += [2,3]; //list = [1, 2, 3]
    //   ^--- list = list.plus(Iterable);
    
    var list=listOf();
    列表+=1//列表=[1];
    //^---list=list.plus(整数);
    列表+=[2,3]//列表=[1,2,3]
    //^---list=list.plus(可编辑);
    
    您的操作员覆盖实施存在两个问题:

    1。
    plus之后的类型不一致

    operator fun ObservableDoubleValue.plus(number: Number): DoubleProperty 
        = SimpleDoubleProperty(get() + number.toDouble())
    
    任何
    可观察到的ubleValue
    实例加上一个
    数字
    ,得到一个
    DoubleProperty
    实例(或者说一个
    SimpleDoubleProperty
    实例)。假设我有一个类型
    ComplexDoubleProperty
    implements
    observedblevalue
    ,您将看到:

    var a = getComplexDoubleProperty()
    a = a + 0.1    //compile error, WTF?
    
    //or even
    var b = SimpleDoubleProperty(0.1)
    b = b + 0.1    //compile error, because b+0.1 is DoubleProperty
    
    你可以看到这种行为毫无意义

    2。a=a+b和a+=b应该相同

    如果您的实现已编译,您将

    var a: DoubleProperty = SimpleDoubleProperty(0.1)  //add DoubleProperty to make it compile
    var b = a
    a += 0.1
    println(b == a)
    
    打印
    true
    ,因为
    +=
    将值设置为原始实例。如果将
    a+=0.1
    替换为
    a=a+0.1
    ,将得到
    false
    ,因为返回了一个新实例。一般来说,
    a=a+b
    a+=b
    在这个实现中并不相同

    为了解决上述两个问题,我的建议是

    operator fun SimpleDoubleProperty.plus(number: Number): SimpleDoubleProperty
            = SimpleDoubleProperty(get() + number.toDouble())
    

    因此,您不需要覆盖
    plusAssign
    。这个解决方案不像您的解决方案那样通用,但是如果您只有
    SimpleDoubleProperty
    计算,那么它是正确的,我相信您是这样做的,因为在您的实现中,
    plus
    总是返回一个
    SimpleDoubleProperty
    实例。

    否,DoubleProperty是Java/JavaFX标准库中的一个类。这并不能回答这个问题。若要评论或要求作者澄清,请在其帖子下方留下评论。-@利亚姆好些了吗POn哪一行有错误?@voddan我在代码中添加了一条评论我接受1。但我不满足于返回我的
    属性的新实例,因为这几乎完全不符合重写
    plus()
    plusAssign()
    的理由。例如,如果其他属性绑定到特定实例,并且您对其进行了
    plusAssign
    ,则
    changeEvent
    将永远不会被触发,并且所有观察者都不会更新。