2016-07-27 66 views
0

我想自己教阶。我试图实现继承,并偶然发现了一个小问题。有人可以帮我吗?无法覆盖从子类中的方法在斯卡拉

问:

  1. 在下面的代码,为什么我无法为对象P6,P7和P8设置x值。
  2. 为什么我无法重写我的子类中的def setX?
object classes { 
    def main (args: Array[String]) { 
     //create objects for class Point 
     val p1 = new Point 
     println("P1 created using no argument constructor: "+p1.toString()) 

     val p2 = new Point 
     p2.setX(1) 
     println("P2 created using setter methods: "+p2.toString()) 

     val p3 = new Point(2) 
     println("P3 created using single argument constructor: "+p3.toString()) 

     val p4 = new Point(3,1) 
     //demonstrating how to use objects within println statement 
     println(s"P4 is created using default constructor and its x value is ${p4.getX} its y value is ${p4.getY} and its id is ${p4.id}") 

     val p5 = new ThreeD 
     println("P5 is created using no argument constructor of 3D class: "+p5.toString) 

     val p6 = new ThreeD(2) 
     println("P6 is created using single argument constructor of 3D class: "+p6.toString) 

     val p7 = new ThreeD(2,3) 
     println("P7 is created using two argument constructor of 3D class: "+p7.toString) 

     val p8 = new ThreeD(2,3,4) 
     p8.setX(5) // has no effect.. why?? 
     println("P8 is created using default constructor of 3D class: "+p8.toString) 
    } 

    //The class name works as a class constructor which can take a number of parameters. 
    class Point (var x: Int, var y: Int) { 
     //demonstrating how to protect the values 
     this.setX(x) 

     /* 
     Scala does not have static methods or static variables. 
     However we can mimic its behavior. 

     Outside the scope of the class, create a companion object for the class 
     Companion objects has same name as that of the class and holds the static members and functions. 
     */ 

     val id = Point.getId 

     //lets define getters and setters 
     def getX() : Int = x 
     def getY() : Int = y 

     def setX(x: Int) { 
      this.x = x 
     } 

     //this is how we override a function 
     //here we implement our custom toString() method 
     override def toString() : String = { 
      return "(%d, %d) and id is %d".format(this.x, this.y, this.id) 
     } 

     //lets define other constructors 

     //to define a constructor, we create a method called "this" 
     //constructor with no arguments 
     def this() { 
      this(0,0) 
     } 

     //constructor with 1 value 
     def this (x: Int) { 
      this(0,0) 
      this.setX(x) 
     } 


    } 

    object Point { 
     //static member 
     private var id = 0 

     //static method 
     private def getId() : Int = { id += 1; id} 
    } 

    //Inheritance 
    class ThreeD (x: Int, y: Int, z: Int) extends Point (x, y) { 
     def this(x: Int, y: Int) { 
      this(0,y,0) 
      this.setX(x) 
     } 

     def this(x: Int) { 
      this(0,0,0) 
      this.setX(x) 
     } 

     def this() { 
      this(0,0,0) 
     } 

     //to override parent class's setX method 
     override def setX(x: Int) { 
      super.setX(x) 
     } 

     override def toString() : String = { 
      return "(%d, %d, %d) and id is %d".format(this.x, this.y, this.z, this.id) 
     } 
    } 
} 
+0

你错过了很多关于斯卡拉案例类,不变性和特质。我建议你得到一本关于这个主题的好书或者教程 – cchantep

+0

是@cchantep我同意。我想我接下来的教程并不完全帮助我。很明显,我错过了很多细节。你能建议好书吗?或者指点我一些不错的文档? – HKrishnan

回答

0

class ThreeD (x: Int, y: Int, z: Int) extends Point (x, y)声明一个类有三个成员。 xy,并且z不是阶级ThreeD的成员,他们只是构造函数的参数。 (你将不得不就其声明为(val x: Int, val y: Int, val z: Int),如果你想让他们成为会员...或者说在这种情况下(override var x: Int, override var y: Int, val z: Int) ...但不这样做 - 见下文)。

因为在Scala中,类的构造函数是相当多类的全身,有时很难分辨出来:你可以在任何地方引用类体中构造函数的参数,如果他们的成员。

它只是开始无所谓,当成员是可变的(不是一件好事在一般情况下,你希望有可变成员作为一个政策问题)。 这里:

override def toString() : String = { 
    return "(%d, %d, %d) and id is %d".format(this.x, this.y, this.z, this.id) 
} 

xy,并且z是指在构造函数的参数,Point重写的成员。 p8.setX致电确实更改成员xp8的值,但它不是p8.toString打印的值 - 它打印构造函数参数的值,即2

的从这个带走:使用可变成员

  1. 避免。你在scala中很少需要它。如果你认为你需要它......再想一想。

  2. 不要给构造函数的参数相同的名称,因为它们初始化,尤其是,如果你打算在类体中访问它们的成员。如果是这样,请将它们声明为override val x,而不仅仅是x

+0

夫妇的事情,我观察到 1.父类成员和子类成员必须是相同的名称。否则scala投诉它无法找到变量 2。我无法覆盖构造函数中子类中的成员 'class ThreeD(override var a:Int,override var b:Int,c:Int)extends Point(a,b){' 我得到错误如下: '错误:重写类Int中的变量a; 值a不能覆盖可变变量 – HKrishnan

+0

1.我不知道你的意思是“必须是同一个名字”。你可以肯定有不同名字的班级成员:) 2.的确,你不能重写'var's,因为它没有任何意义:它是可变的,它必须是相同的类型,所以,重写它将具有与为其分配不同的值完全相同的效果。 – Dima