Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Overriding Companion Object Values and Scala MatchError

Can someone clarify why the following code causes a MatchError? What does a MatchError mean in this case?

class A {
  def g = A.f
}

object A {
  val f = "Object A"
}


class B extends A {
  override val A.f = "Object B"
}

val b = new B
b.g

Given this doesn't work, is there a way to override a companion object val or def similar to this?

like image 796
deepkimo Avatar asked Oct 05 '22 06:10

deepkimo


1 Answers

First, to why you're seeing a MatchError. A value on an object (A.f) is considered a stable identifier (as Scala reference says, "Stable members are [...] members introduced by object definitions or by value definitions of non-volatile types").

Here's what the typer output looks like:

object A extends scala.AnyRef {
    ...
    private[this] val f: String = "Object A";
    <stable> <accessor> def f: String = A.this.f
}

When used in an assignment, the compiler "desugars" assignment of this stable identifier (it being stable is a necessary condition) into pattern matching:

<synthetic> private[this] val x$1: Unit = ("Object B": String("Object B") @unchecked) match {
    case A.f => ()
}

It can't match "Object B" against a pattern "Object A", so it throws a MatchError.

To your larger question: you can't/shouldn't override values and methods on a companion object. Polymorphism applies to classes and their instances, not to static methods or values. There's probably a better way to think about your program that doesn't involve overriding vals/defs on a companion object.

like image 139
Alex Yarmula Avatar answered Oct 11 '22 14:10

Alex Yarmula