Kotlin泛型和运算符重载

时间:2018-10-31 22:01:49

标签: generics kotlin operator-overloading

我想做这样的事情

data class TestGen<T: Number>(var x : T, var y : T)

public operator<T:Number> fun Int.plus(p:TestGen<T>) = TestGen(this+p.x,p.y)

那我该怎么办呢?或其他任何想法做同样的事情? 因为我想做这样的事情

public operator fun Int.plus(p:TestGen<Float>) = TestGen(this+p.x,p.y)
public operator fun Int.plus(p:TestGen<Double>) = TestGen(this+p.x,p.y)

1 个答案:

答案 0 :(得分:1)

首先,在扩展功能的声明中出现语法错误。其次,Number不会自动定义将+加另一个数字的功能。因此,使用Number作为通用基本类型会产生问题。不幸的是,您需要创建希望对所有数字类型均有效的所有排列。

打破现状...

operator <T: Number> fun Int.plus(p:TestGen<T>) = TestGen(this+p.x,p.y)

是无效的语法。以下内容更为正确,但由于“类Number上不存在plus方法”的原因,仍无法编译:

operator fun <T: Number> Int.plus(p:TestGen<T>) = TestGen(this+p.x,p.y)

因此,要解决此问题,您真正需要的是删除该函数的通用参数,并具体说明所支持的每种类型:

@JvmName("IntPlusTestGenWithInt")
operator  fun Int.plus(p:TestGen<Int>) = TestGen(this+p.x,p.y)
@JvmName("IntPlusTestGenWithLong")
operator  fun Int.plus(p:TestGen<Long>) = TestGen(this+p.x,p.y)
@JvmName("IntPlusTestGenWithDouble")
operator  fun Int.plus(p:TestGen<Double>) = TestGen(this+p.x,p.y)
@JvmName("IntPlusTestGenWithFloat")
operator  fun Int.plus(p:TestGen<Float>) = TestGen(this+p.x,p.y)
// etc

JvmName注释是必需的,因为您正在创建扩展方法,这些扩展方法仅在JVM擦除的通用参数上有所不同。因此,即使您不会从Kotlin代码中看到,由Kotlin生成的字节码在内部也必须按名称区分每个扩展方法。

对于要添加和添加的所有类型的功能,您都需要类似的功能变体。并且您应该考虑对那些不再有用的数字进行处理,例如,将Double的小数部分添加到Int中。