Проблемы с пониманием того, как класс работает в Scala - PullRequest
0 голосов
/ 15 марта 2019

Мой вопрос: как последние println(salt.value()) выводят значение 5.0. Я думал, что утверждение crystal.grow() добавит 1 к соли 6, а выражение 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 ]

1 голос
/ 15 марта 2019

Это все потому, что у вас есть переопределить метод 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

}

Выход:

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

}

Выход:

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

Надеюсь, это поможет!

0 голосов
/ 15 марта 2019

Используя типы, вы по существу даете подсказки компилятору для проверки вашего кода.Поэтому, сказав 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

Что касается того, почему crystal и salt указывают на один и тот же объект.Scala / Java делает копии только для примитивных типов (например, Int или Double; как и во многих других языках), т. Е. Для объектов мы просто создаем указатель на тот же объект.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...