无法在scala

时间:2016-07-27 22:27:30

标签: scala inheritance override

我正在尝试自学scala。我试图实现继承并偶然发现一个小问题。有人可以帮我吗?

问题:

  1. 在下面的代码中,为什么我无法为对象p6,p7和p8设置x的值。
  2. 为什么我无法覆盖子类中的def setX?
  3. 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)
            }
        }
    }
    

1 个答案:

答案 0 :(得分:0)

class ThreeD (x: Int, y: Int, z: Int) extends Point (x, y) 声明一个有三个成员的类。 xyz不是类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)
}

xyz引用构造函数参数,被覆盖的Point成员。 p8.setX调用确实更改x的成员p8的值,但它不是p8.toString打印的内容 - 它会打印构造函数的值参数,2

远离这个:

  1. 避免使用可变成员。你很少需要scala。如果你认为你需要它......再想一想。

  2. 不要给构造函数参数赋予与它们初始化的成员相同的名称,特别是,如果您打算在类体中访问它们。如果您这样做,请将其声明为override val x,而不只是x