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
Kotlin 传递和访问传递给需要它的类构造函数的子类型的值和函数';s超型_Kotlin_Inheritance - Fatal编程技术网

Kotlin 传递和访问传递给需要它的类构造函数的子类型的值和函数';s超型

Kotlin 传递和访问传递给需要它的类构造函数的子类型的值和函数';s超型,kotlin,inheritance,Kotlin,Inheritance,我会尽量简单。假设我有一个父类,其函数如下所示,将位置参数作为点数据类 open class Obj(val pos:Point) { fun foo() : Double { return 5.0 + pos.x * pos.y * pos.z } } data class Point(val x:Double, val y:Double, val z:Double) 为了彻底起见,这里是Point数据类 open class Obj(val pos:Poi

我会尽量简单。假设我有一个父类,其函数如下所示,将位置参数作为点数据类

open class Obj(val pos:Point) {
    fun foo() : Double {
        return 5.0 + pos.x * pos.y * pos.z
    }
}
data class Point(val x:Double, val y:Double, val z:Double)
为了彻底起见,这里是Point数据类

open class Obj(val pos:Point) {
    fun foo() : Double {
        return 5.0 + pos.x * pos.y * pos.z
    }
}
data class Point(val x:Double, val y:Double, val z:Double)
因此,我有多个子类继承自Obj类,但实现了一个附加函数,该函数在每个子类中命名相同,并在父类中调用一个函数

class Cube(pos:Point) : Obj(pos) {
    fun number() : Double {
        return 10.0 * foo()
    }
}

class Sphere(pos:Point) : Obj(pos) {
    fun number() : Double {
        return 20.0 * foo()
    }
}
我的问题是,如果我在某个地方有一个函数,它接收从Obj继承而不是Obj本身的对象,那么我如何确保它们属于自己的子类型而不是超类型

例如,我目前的函数如下所示

fun foo2(obj:Obj) {
    println(obj.number()) // throws error because obj doesn't have method number()
}

处理这种情况的正常方法是向基类添加一个抽象方法,并让子类实现它。这样,只要有基类引用,编译器就知道该方法可用

这将要求基类本身是抽象的,因此不能直接实例化它。(如果
foo()
仅由
number()
实现使用,那么对其他类隐藏它可能是有意义的。)

但是,如果您需要基类是可实例化的,那么这就更棘手了:没有简单的方法来指定“仅子类”。根据您的具体需求,您可以允许传递基类,并让它提供
number()
的默认实现:


处理这种情况的正常方法是向基类添加一个抽象方法,并让子类实现它。这样,只要有基类引用,编译器就知道该方法可用

这将要求基类本身是抽象的,因此不能直接实例化它。(如果
foo()
仅由
number()
实现使用,那么对其他类隐藏它可能是有意义的。)

但是,如果您需要基类是可实例化的,那么这就更棘手了:没有简单的方法来指定“仅子类”。根据您的具体需求,您可以允许传递基类,并让它提供
number()
的默认实现:


好的,根据Animesh Sahu的建议,我在基类中实现了一个名为ObjI的接口,并要求每个实现重写number()函数。我结合了gidds给出的答案,建议创建一个调用另一个函数的函数。基类中的number()函数只调用foo()函数

数据类点(val x:Double,val y:Double,val z:Double)
接口对象{
有趣的数字():双
}
开放类Obj(val p:点):ObjI{
重写fun number()=foo()
fun foo():双倍{
返回5.0+p.x*p.y*p.z
}
}
类球体(p:点):Obj(p){
覆盖有趣的数字():双精度{
return 10.0*super.foo()
}
}
类立方体(p:点):Obj(p){
覆盖有趣的数字():双精度{
return 20.0*super.foo()
}
}
趣味主线(args:Array){
val s=球体(点(13.0,6.0,1.0))
val c=立方体(点(13.0,6.0,1.0))
printem(s)
printem(c)
}
趣味打印(o:Obj){
println(o.编号())
}

好的,根据Animesh Sahu的建议,我在基类中实现了一个名为ObjI的接口,并要求每个实现重写number()函数。我结合了gidds给出的答案,建议创建一个调用另一个函数的函数。基类中的number()函数只调用foo()函数

数据类点(val x:Double,val y:Double,val z:Double)
接口对象{
有趣的数字():双
}
开放类Obj(val p:点):ObjI{
重写fun number()=foo()
fun foo():双倍{
返回5.0+p.x*p.y*p.z
}
}
类球体(p:点):Obj(p){
覆盖有趣的数字():双精度{
return 10.0*super.foo()
}
}
类立方体(p:点):Obj(p){
覆盖有趣的数字():双精度{
return 20.0*super.foo()
}
}
趣味主线(args:Array){
val s=球体(点(13.0,6.0,1.0))
val c=立方体(点(13.0,6.0,1.0))
printem(s)
printem(c)
}
趣味打印(o:Obj){
println(o.编号())
}

只需为
Cube
Sphere
创建一个公共接口,该接口定义了它们的
number()
函数。@AnimeshSahu我只是试着认为这可能行得通,但我很难理解如何从Obj类继承并实现该接口。我是Kotlin的新手,文档中显示了对其中一种的独家使用,我找不到两者结合的示例,只需为
Cube
Sphere
创建一个通用接口,定义它们的编号()funciton.@AnimeshSahu我只是尝试了一下,认为它可能会起作用,但我很难弄清楚如何从Obj类继承并实现接口。我对Kotlin还比较陌生,文档中显示了其中一个的独家使用,我找不到一个两者同时使用的例子
data class Point(val x:Double, val y:Double, val z:Double)


interface ObjI {
  fun number() : Double
}

open class Obj(val p:Point) : ObjI {
  override fun number() = foo()
  
  fun foo() : Double {
    return 5.0 + p.x * p.y * p.z
  }
}

class Sphere(p:Point) : Obj(p) {
  override fun number() : Double {
    return 10.0 * super.foo() 
  }
}

class Cube(p:Point) : Obj(p) {
  override fun number() : Double {
    return 20.0 * super.foo()
  }
}

fun main(args: Array<String>) {
  val s = Sphere(Point(13.0, 6.0, 1.0))
  val c = Cube(Point(13.0, 6.0, 1.0))
  printem(s)
  printem(c)
}

fun printem(o:Obj) {
  println(o.number())
}