我正在尝试自学scala。我试图实现继承并偶然发现一个小问题。有人可以帮我吗?
问题:
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 :(得分:0)
class ThreeD (x: Int, y: Int, z: Int) extends Point (x, y)
不声明一个有三个成员的类。 x
,y
和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)
}
x
,y
和z
引用构造函数参数,不被覆盖的Point
成员。 p8.setX
调用确实更改x
的成员p8
的值,但它不是p8.toString
打印的内容 - 它会打印构造函数的值参数,2
。
远离这个:
避免使用可变成员。你很少需要scala。如果你认为你需要它......再想一想。
不要给构造函数参数赋予与它们初始化的成员相同的名称,特别是,如果您打算在类体中访问它们。如果您这样做,请将其声明为override val x
,而不只是x
。