[英]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. 至于为什么crystal
和salt
指向同一物体。 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.