kotlin:通用于不同的类型
我需要这样的线性函数:
class Linear(val a : Double, val b : Double) { fun eval(in : Double) { return a*in + b } }
然后,我需要为矢量相同的东西。
class Vector3d(val a1 : Double, val a2 : Double, val a3 : Double) { // use operator overloading https://kotlinlang.org/docs/reference/operator-overloading.html to make +, -, /, *, etc. possible for vectors } class Linear(val a : Vector3d, val b : Vector3d) { fun eval(in : Vector3d) { return a*in + b } }
正如你所看到的,两个线性类是相同的(参数类型除外)。 现在,我不能使类通用,因为Double和Vector3d没有共同的超类。
如果我只想写一次Linear,我唯一的选择就是我自己的Double-type,它与Vector3d有一个共同的接口。 但是,这意味着我不能在源代码中使用0,但是我必须在任何地方使用MyDouble(0)。 我可以重载线性的构造函数接受双打,并在内部创建MyDouble对象,但是,我需要为我的API中的每一个单一的方法。
有更好的解决方案吗?
您可以通过定义一个具有两个实现/子类的接口/类来引入间接级别:一个用于原始双精度,另一个用于Vector3d
。 但是,您可能会发现不希望的开销。 例如:
interface Arithmetical<A : Arithmetical<A>> { operator fun plus(other: A): A operator fun minus(other: A): A operator fun times(other: A): A operator fun div(other: A): A } class Linear<A : Arithmetical<A>>(val a: A, val b: A) { fun eval(`in`: A): A { return a * `in` + b } } class ArithmeticalDouble(val value: Double) : Arithmetical<ArithmeticalDouble> { override fun plus(other: ArithmeticalDouble) = ArithmeticalDouble(value + other.value) override fun minus(other: ArithmeticalDouble) = ArithmeticalDouble(value - other.value) override fun times(other: ArithmeticalDouble) = ArithmeticalDouble(value * other.value) override fun div(other: ArithmeticalDouble) = ArithmeticalDouble(value / other.value) } class Vector3d(val a1: Double, val a2: Double, val a3: Double) : Arithmetical<Vector3d> { override fun plus(other: Vector3d): Vector3d = TODO() override fun minus(other: Vector3d): Vector3d = TODO() override fun times(other: Vector3d): Vector3d = TODO() override fun div(other: Vector3d): Vector3d = TODO() }
这使得使用原始双精度的操作变得更加困难,因为现在您必须将它们打包并解包,但它确实允许您使用泛型来定义Linear
。
实际上,你在技术上可以用泛型创建一个类,但是类不会知道如何将T与T相乘,因为它是Any
一个子类, Any
不支持这个操作。 通过聪明的演员,你可以评估,给出了什么样的T:
class Linear<T>(val a: T, val b: T) { fun eval(c: T): Any { when { a is Double -> return a * c as Double + b as Double a is Double -> return a * c as Vector3d + b as Vector3d else -> return Unit } }
有关更多信息,请参阅Kotlin-docs上的泛型 。
我不会考虑这个好的做法,因为这个方法没有明确的(和类型保存的)返回类型,而且非常不灵活,但是至少它为你的论点提供了类型安全性。
另一种方法是使用Number
(或Double
)作为Vector3d
的超类,并将这些方法作为长度来实现。 这也不会是一个很好的做法,但至少可以使用<Number>
作为泛型。