0

If I have a case class that inherits another class like this

  class Person(name: String) {

  }

case class Male() extends Person("Jack") {
  def f = super.name // Doesn't work 

}

How to get the name property from Male class ?

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
Adelin
  • 18,144
  • 26
  • 115
  • 175

2 Answers2

5
class Person(name: String) {

In this declaration, name is not a field of the class, it is just a constructor parameter. So it is accessible inside the constructor, but not outside (including in a subclass). You can make it a field by making it a val:

class Person(val name: String) {

Confusingly, constructor parameters for a case class are also fields even without val

Tim
  • 26,753
  • 2
  • 16
  • 29
  • 1
    This is standard misundestanding that `name` is not a field. It's `private[this]` field. If it weren't a field you couldn't access it with `this` inside `Person`: `class Person(name: String) { this.name }`. – Dmytro Mitin Oct 02 '20 at 16:37
  • @DmytroMitin If you follow the link in that post you will see this: "That's all true, but it should be treated as an implementation technique. That's why the spec is silent about it." In other words, the specification does not say that it is a field. – Tim Oct 02 '20 at 16:46
  • Right, this behavior is not specified, but currently it is a field, otherwise you couldn't access it with `this`. – Dmytro Mitin Oct 02 '20 at 16:49
  • It's my post, I followed the link :) – Dmytro Mitin Oct 02 '20 at 16:50
  • But since it is not a field in the specification, the fact that you can access it via `this` is an implementation detail of the current compiler and should not be relied on. I also think it is conceptually easier to think of it as a parameter rather than a field. – Tim Oct 02 '20 at 16:50
  • 1
    Right, you shouldn't rely on this, but it is a field in current implementation :) – Dmytro Mitin Oct 02 '20 at 16:52
  • 2
    Right, but I was talking about the language, not the implementation :) – Tim Oct 02 '20 at 16:53
  • By the way, next implementation is the same https://scastie.scala-lang.org/BT1GBOASTSOJP22HNIy88A (0.27.0-RC1) – Dmytro Mitin Oct 02 '20 at 16:55
  • And you write "`name` is not a field of the class" in your answer. It being not a field is also not specified :) – Dmytro Mitin Oct 02 '20 at 17:16
1

Try to make name a val (or at least protected val) in Person, then it will be accessible in Male

class Person(val name: String)

case class Male() extends Person("Jack") {
  def f = name
}

When you wrote class Person(name: String) you actually created class Person(private[this] val name: String) so name was not accessible in Male.

https://stackoverflow.com/a/62686327/5249621

Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66