Problem with passing parameters through a set of constructors

My question is about scala inheritance details. I have the following code.

package scalasandbox object Main { def main(args: Array[String]): Unit = { val creature: Creature = new Human("First") creature.rename("Second") creature.introduce } } class Creature(var name: String) { def introduce = println("I'm creature: " + name) def rename(newName: String) = { println("Creature was renamed to: " + newName) name = newName } } class Human(name: String) extends Creature(name) { override def introduce = println("I'm Human: " + name) } 

which produces the following conclusion

 Creature was renamed to: Second I'm human: First 

I expect it to be “I'm Human: Second,” because the renaming method should change the value of the field. I discovered the Human class with a decompiler:

 package scalasandbox; import scala.Predef.; import scala.ScalaObject; import scala.collection.mutable.StringBuilder; import scala.reflect.ScalaSignature; @ScalaSignature(bytes="\006\001\0212A!\001\002\001\013\t)\001*^7b]*\t1!\001\007tG\006d\027m]1oI\n|\007p\001\001\024\007\0011!\002\005\002\b\0215\t!!\003\002\n\005\tA1I]3biV\024X\r\005\002\f\0355\tABC\001\016\003\025\0318-\0317b\023\tyABA\006TG\006d\027m\0242kK\016$\b\002C\t\001\005\003\005\013\021\002\n\002\t9\fW.\032\t\003'Yq!a\003\013\n\005Ua\021A\002)sK\022,g-\003\002\0301\t11\013\036:j]\036T!!\006\007\t\013i\001A\021A\016\002\rqJg.\033;?)\taR\004\005\002\b\001!)\021#\007a\001%!)q\004\001C!A\005I\021N\034;s_\022,8-Z\013\002CA\0211BI\005\003G1\021A!\0268ji\002") public class Human extends Creature implements ScalaObject { private final String name; public void introduce() { Predef..MODULE$.println(new StringBuilder().append("I'm Human: ").append(this.name).toString()); } public Human(String name) { super(name); } } 

and see "private final String name;" there. I think he is hiding the creature’s name field. AND

 Predef..MODULE$.println(new StringBuilder().append("I'm Human: ").append(this.name).toString()); 

this stuff also looks suspicious due to "this.name" instead of calling the "this.name ()" method. Can someone explain where my error is and what is the correct way to implement these two classes?

+4
source share
3 answers

The name variable that you use in the Human class enables the constructor parameter of Human , and Scala automatically creates private vals for the constructor parameters that you use outside the constructor. This is unfortunate in your case. You can prevent this, for example, by naming your parameter in Human differently, for example. nm :

 class Human(nm: String) extends Creature(nm) 
+4
source

try changing this line:

 class Human(foo: String) extends Creature(foo) { 

so that you do not hide the name .

+3
source

If Creature intended only for a subclass, I would advise you to abstract both the class and name according to my answer here:

Idiomatic Scala way to handle field names of base and derived classes?

One of the advantages of this method is that then it becomes much easier to use case classes for specific, specific, subclasses

+2
source

All Articles