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
Generics kotlin:不同类型的泛型_Generics_Kotlin - Fatal编程技术网

Generics kotlin:不同类型的泛型

Generics kotlin:不同类型的泛型,generics,kotlin,Generics,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://kotli

我需要这样的线性函数:

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类型,它与Vector3d有一个公共接口。然而,这意味着我不能再在源代码中使用0,但我必须在任何地方使用MyDouble(0)。我可以重载Linear的构造函数来接受double,并在内部创建MyDouble对象,但是,我需要为API中的每个方法都这样做


有更好的解决办法吗

事实上,从技术上讲,您可以使用泛型创建一个类,但该类不知道如何将t与t相乘,因为它是的子类,
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
        }
}
class线性(val a:T,val b:T){
乐趣评估(c:T):有吗{
什么时候{
a是双精度->返回a*c为双精度+b为双精度
a是双精度->返回a*c作为矢量3D+b作为矢量3D
else->返回单元
}
}
有关更多信息,请参阅Kotlin文档

我不会考虑这个好的实践,因为该方法没有明确的(类型保存)返回类型,而且非常不灵活,但至少它为您的参数提供了类型安全性。


另一种选择是使用
数字
(或
双精度
)作为
Vector3d
的超级类,并将方法实现为length。这也不是一个很好的实践,但至少可以将
用作泛型。

您可以通过定义一个接口/类来引入一个间接级别,该接口/类有两个实现/子类:一个用于原语双精度,另一个用于用户
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()
}
接口算术{
操作员乐趣附加(其他:A):A
操作员乐趣减号(其他:A):A
操作员娱乐时间(其他:A):A
操作员娱乐组(其他:A):A
}
线性类(值a:a,值b:a){
有趣的评价(`in`:A):A{
在`+b中返回a*`
}
}
类算术双精度(val值:双精度):算术{
重写fun plus(其他:算术加倍)=算术加倍(值+其他.value)
覆盖fun减号(其他:算术加倍)=算术加倍(值-其他.value)
覆盖乐趣时间(其他:算术双倍)=算术双倍(值*其他.value)
覆盖fun div(其他:算术双精度)=算术双精度(值/其他.value)
}
类Vector3d(val a1:Double,val a2:Double,val a3:Double):算术{
覆盖fun plus(其他:Vector3d):Vector3d=TODO()
覆盖乐趣减号(其他:Vector3d):Vector3d=TODO()
覆盖乐趣时间(其他:Vector3d):Vector3d=TODO()
覆盖fun div(其他:Vector3d):Vector3d=TODO()
}

这使得在使用原语double时会听到更多的杂音,因为现在您必须对它们进行包装和展开,但它确实允许您使用泛型来定义
Linear

您没有显示
Vector3d
如何支持
*
+
操作。您肯定需要一个通用的父类/接口,否则您会被困在未绑定泛型。