scalaself-type

Requiring a certain trait -> Self type annotation?


I'd like to require a case class to also implement at least one of certain traits.

I thought, I could use self-type annotations like this:

case class DisqualifiedDate(override val paths: Set[DatePath],
     override val cal: Calendar) extends CalendricDate(paths,cal){

     this: DateError =>

     val stringPrefix = "DisqualifiedDate"
 }

sealed trait DateError
trait Circular extends DateError
trait Contradictory extends DateError
trait Inaccessible extends DateError

However instantiating with a mixin doesn't compile. So, when I do:

val date = new DisqualifiedDate(Set(datePath),cal) with Circular

this doesn't compile.

Am I doing something wrong or this the whole approach flawed?

SOLVED: It works perfectly with a normal class, i.e. non-case class. I'm not sure why this is so, but I'm OK with that.


Solution

  • A stand-alone case class (i.e. without extends or mixins) can't be self typed.

    Think about it. A case class is both a class definition and a singleton instantiation. A self-type reference means that instantiation can't take place without the specified self-type mixed in.

    You either have to make it a class definition without the automatic singleton creation, or mix in the required trait when the case class is defined.

    class DisqualifiedDate(override val paths: Set[DatePath],
                           override val cal: Calendar
                          ) extends CalendricDate(paths,cal) {
      this: DateError =>
      . . .
    

    Or ...

    case class DisqualifiedDate(override val paths: Set[DatePath],
                                override val cal: Calendar
                               ) extends CalendricDate(paths,cal) with DateError {
      this: DateError =>  // now redundant
      . . .