0

The question is how C trait uses str field specified in D class. D extends from A so it doesn't have str specified in any contract. Even though C is able to use it. When I remove str from D compiler won't compile this code. How does it know that str from D unrelated to str in B is the same thing. I would expect this behavior in dynamically typed language but not in one with static typing.

trait A {
  def receive(): PartialFunction[String, Any]
}

trait B extends A {
  def str: String
}

trait C extends B {
  abstract override def receive(): PartialFunction[String, Any] =
    cReceive.orElse(super.receive())

  val cReceive: PartialFunction[String, Any] = {
    case "MemberUp" ⇒ s"$str"
  }
}

class D extends A {
  override def receive(): PartialFunction[String, Any] = {
    case _ ⇒
  }

  def str: String = "My string"
}

class E extends D with C

object Main extends App {
  private val e = new E
  println(e.receive().apply("MemberUp"))
}
Julian Rubin
  • 1,175
  • 1
  • 11
  • 23

1 Answers1

0

The magic is happening in E.

Basically B says "there is going to be a method str returning string". Now, when it is called in C, an implementation is looked at.

If E would have defined str then everything would be clear. In this case, str is taken from D. When the compiler is building E, it first defines which methods are available and then looks for implementations in the order defined by linearization (see Linearization order in Scala). This means that an implementation is available as if it was defined in E (because def str IS part of E.

Note: if you would have changed recieve in D to return something else, then str would still be returned. This is because from the linerarization order C implementation comes before D and D becomes the super of C.

Assaf Mendelson
  • 12,701
  • 5
  • 47
  • 56
  • Worth adding that a concrete definition overrides an abstract declaration, no matter the linearization order. http://scala-lang.org/files/archive/spec/2.12/05-classes-and-objects.html#class-members The spec calls them "matching" members. – som-snytt May 13 '17 at 06:54
  • Thanks for explanation! – Julian Rubin May 13 '17 at 10:39