简体   繁体   English

难以理解Scala中的课堂工作方式

[英]Trouble understanding how class works in Scala

My question is how does the last println(salt.value()) print a value of 5.0. 我的问题是最后一个println(salt.value())打印5.0值。 I thought that the statement crystal.grow() would add 1 to the salt value of 6 and the statement salt.value() would multiply 7 by 0.5 which then give the answer 3.5. 我认为语句crystal.grow()会将1的盐值加1,而语句salt.value()会将7乘以0.5,然后得出答案3.5。 What am I missing here? 我在这里想念什么?

abstract class Crystal(var size: Double) {

def value(): Double

def grow(): Unit = {
    this.size += 1.0
}

}

class Quartz(quartzSize: Double) extends Crystal(quartzSize) {

override def value(): Double = {
    this.size * 5.0
}

}

class Salt(saltSize: Double) extends Crystal(saltSize) {

override def value(): Double = {
    this.size * 0.5
}

override def grow(): Unit = {
    this.size += 4.0
}

}

object Part1 {

def main(args: Array[String]): Unit = {
    val quartz: Quartz = new Quartz(5.0)
    val salt: Salt = new Salt(6.0)
    val crystal: Crystal = salt
    crystal.grow()
    println(salt.value())

}

}

Output: 输出:

5.0

It's all because you have override grow() method in the salt class. 这是因为您在salt类中具有重写grow()方法。 Please find explaination as below. 请找到以下说明。

With override grow() in the Salt : 在Salt中使用override grow():

abstract class Crystal(var size: Double) {

  def value(): Double

  def grow(): Unit = {
    println("Cystal.value = " + this.size)
    this.size += 1.0
  }

}

class Quartz(quartzSize: Double) extends Crystal(quartzSize) {

  println("quartzSize = " + quartzSize) // Size = 5.0
  override def value(): Double = {
    println("Quartz.value = " + this.size) // Size = 5.0
    this.size * 5.0
  }

}

class Salt(saltSize: Double) extends Crystal(saltSize) {

  println("saltSize = " + saltSize) // Size = 6.0
  override def value(): Double = {
    println("Salt.value = " + this.size) // Size = 10
    this.size * 0.5 // size = 5.0
  }

  override def grow(): Unit = {
    println("Salt.grow() = " +this.size) // Size = 6.0
    this.size += 4.0 // Size = 6.0 + 4.0
  }

}

object Test extends App {

  val quartz: Quartz = new Quartz(5.0) // You have set Size = 5.0 
  val salt: Salt = new Salt(6.0) // You have set Size = 6.0
  val crystal: Crystal = salt // size = 6.0 (saltSize)
  println("Test - crystal.grow() =" + crystal.grow()) // Size = 10.0  -- It calls the Salt.grow method as you have override the grow method.
  println("Test - salt.value() =" +salt.value()) // size = 5.0
  println("Test - quartz.value() ="+quartz.value()) // size = 25

}

Output: 输出:

quartzSize = 5.0
saltSize = 6.0
Salt.grow() = 6.0
Test - crystal.grow() =()
Salt.value = 10.0
Test - salt.value() =5.0
Quartz.value = 5.0
Test - quartz.value() =25.0

Without overriding grow() in the Salt : 不覆盖Salt中的grow():

abstract class Crystal(var size: Double) {

  def value(): Double

  def grow(): Unit = {
    println("Cystal.value = " + this.size) // 6.0 
    this.size += 1.0  // size = 7.0 
  }

}
class Quartz(quartzSize: Double) extends Crystal(quartzSize) {

  println("quartzSize = " + quartzSize) // Size = 5.0
  override def value(): Double = {
    println("Quartz.value = " + this.size) // Size = 5.0
    this.size * 5.0
  }

}

class Salt(saltSize: Double) extends Crystal(saltSize) {

  println("saltSize = " + saltSize) // Size = 6.0
  override def value(): Double = {
    println("Salt.value = " + this.size) // Size = 10
    this.size * 0.5 // size = 5.0
  }

  //override def grow(): Unit = {
   // println(this.size) // Size = 6.0
   // this.size += 4.0 // Size = 6.0 + 4.0
  //}

}

object Test extends App {

  val quartz: Quartz = new Quartz(5.0) // You have set Size = 5.0 
  val salt: Salt = new Salt(6.0) // You have set Size = 6.0
  val crystal: Crystal = salt // size = 6.0 (saltSize)
  println("Test - crystal.grow() =" + crystal.grow()) // Size = 7.0  -- It calls the Cystal.grow method as we are not overriden the grow method.
  println("Test - salt.value() =" +salt.value()) // size = 3.5
  println("Test - quartz.value() ="+quartz.value()) // size = 25

}

Output : 输出:

quartzSize = 5.0
saltSize = 6.0
Cystal.value = 6.0
Test - crystal.grow() =()
Salt.value = 7.0
Test - salt.value() =3.5
Quartz.value = 5.0
Test - quartz.value() =25.0

Hope it helps! 希望能帮助到你!

Using types you essentially give the compiler hints to check your code. 使用类型,您实际上会给编译器提示检查代码的提示。 So by saying val crystal: Crystal = salt , you just tell it to treat crystal as the less-specific class Crystal from now on (ie, formally check your code only considering this). 因此,通过说val crystal: Crystal = salt ,您只需告诉它从现在开始就将crystal视为不太具体的类Crystal (即,仅考虑此点就正式检查代码)。

You do not change the actual object in this case though (even more so because you cannot have instances of an abstract class, which Crystal is). 但是,在这种情况下,您无需更改实际的对象(甚至更多,因为您不能拥有Crystal所属的抽象类的实例)。 So if you say crystal.grow() , the interpreter will still look for the most specific version of grow() that it can find, in this case the overridden one in Salt . 因此,如果您说crystal.grow() ,解释器仍会寻找它可以找到的最特定版本的grow() ,在这种情况下,是Salt被覆盖的版本。 You can check this with getClass : 您可以使用getClass进行检查:

scala> salt.getClass
res1: Class[_ <: Salt] = class Salt

scala> crystal.getClass
res2: Class[_ <: Crystal] = class Salt

As for why crystal and salt point to the same object. 至于为什么crystalsalt指向同一物体。 Scala/Java only make copies for primitive types (eg, Int or Double; like many other languages), ie, for objects we simply create a pointer to the same object. Scala / Java只为原始类型(例如,Int或Double;与许多其他语言类似)创建副本,即,对于对象,我们仅创建指向同一对象的指针。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM