2016-07-27 65 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