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

时间:2019-03-15 03:58:14

标签: java scala class methods

我的问题是最后一个println(salt.value())如何输出5.0值。我认为语句crystal.grow()将1的盐值加1,而语句salt.value()将7乘以0.5,然后得到答案3.5。我在这里想念什么?

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())

}

}

输出:

5.0

2 个答案:

答案 0 :(得分:1)

全部是因为您在salt类中具有重写生长()方法。请找到以下说明。

在Salt中覆盖了grow():

differences = []
for i in range(889):
    try:
        differences.append(relativedelta(death_date_new[i], admittance_date[i]).years)
    except TypeError:
        i = "Still Alive"
        differences.append(i)

输出:

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

}

在Salt中不覆盖grow():

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

输出:

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

}

希望有帮助!

答案 1 :(得分:0)

实际上,使用类型可以为编译器提供检查代码的提示。因此,只需说出val crystal: Crystal = salt,您就可以告诉它从现在起将crystal视为次特定类Crystal(即,仅考虑这一点就正式检查您的代码)。

但是,在这种情况下,您不会更改实际的对象(甚至更是如此,因为您不能拥有Crystal是的抽象类的实例)。因此,如果您说crystal.grow(),则解释器仍会寻找它可以找到的最特定版本的grow(),在这种情况下,Salt中被覆盖的版本。您可以使用getClass进行检查:

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

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

为什么crystalsalt指向同一个对象。 Scala / Java只为原始类型(例如Int或Double;与许多其他语言类似)创建副本,即对于对象,我们只需创建指向同一对象的指针即可。