Search code examples
scalainheritanceoverridingcase-class

In Scala, how can an Inner case class consistently override a method?


I recently discovered that Scala compiler has an interesting feature for case class: Since it generates both a class & an object signature, if defined as an inner class, it can be used to override an abstract type definition and a function definition of its super class with minimal boilerplate code, here is an example:

object InnerCaseClassOverridingBoth {

  trait AALike

  trait SS {
    type AA <: AALike
    def AA(): AnyRef
  }

  trait SS_Clear extends SS {
    def AA(): AnyRef
  }

  class SSA extends SS_Clear {
    case class AA() extends AALike
  }
  object SSA extends SSA {}
}

This will compile without any error. However the shortcut stops here, if the function definition def AA is parameterized, then neither the inner case class nor inner object is capable of overriding it: the apply function of the inner object doesn't automatically expand to a method of its outer class:

  trait SS_Parameterised extends SS {
    def AA(ii: Int): AnyRef
  }

  class SSB extends SS_Parameterised {
    case class AA(ii: Int) extends AALike
  }
  object SSB extends SSB {}

This gives an error:

class SSB needs to be abstract, since method AA in trait
SS_Parameterised of type (ii: Int)AnyRef is not defined
    class SSB extends SS_Parameterised {

My question is, is there a shortcut in this case? Why is the Scala compiler is designed to link case 1 but not case 2?


Solution

  • OK I found 2 ways of doing this

    Method 1: overriden by case class:

      trait SS_Parameterised {
        type AA <: AALike
        def AA: Int => AnyRef
      }
    

    Method 2: overriden by implicit class:

      trait SS_Parameterised {
        type AA <: AALike
        implicit def AA(ii: Int): AnyRef
      }
    
      class SSB extends SS_Parameterised {
        implicit class AA(ii: Int) extends AALike
      }
    

    End of story :) One case class overriding 2 declarations? No problem.

    (Method 2 works as scala internally generates an implicit function for every implicit class)