Scala -- mutually exclusive traits

487 views Asked by At

Is there a way to define a collection of alternatives of a common type:

trait Mutability
trait Mutable extends Mutability
trait Immutable extends Mutability

and have the compiler preclude something like:

object Hat extends Mutable with Immutable

I believe I can force some compiler error by having a common, conflicting member but the error message is a bit oblique:

trait Mutability
trait Mutable extends Mutability { protected val conflict = true }
trait Immutable extends Mutability { protected val conflict = true }

object Hat extends Mutable with Immutable

<console>:10: error: object Hat inherits conflicting members:
value conflict in class Immutable$class of type Boolean  and
value conflict in class Mutable$class of type Boolean
(Note: this can be resolved by declaring an override in object Hat.)
   object Hat extends Immutable with Mutable

Is there a more direct way to express this constraint and not permit someone to work around it by taking the hint offered by the compiler (override 'conflict' in Hat)?

Thanks for any insights

1

There are 1 answers

3
Daenyth On

I think this might work

sealed trait Mutability
case object Immutable extends Mutability
case object Mutable extends Mutability

trait MutabilityLevel[A <: Mutability]

class Foo extends MutabilityLevel[Immutable.type]

This (ab?)uses the fact that you can't extend the same trait twice with different parameterization

scala> class Foo extends MutabilityLevel[Immutable.type] with MutabilityLevel[Mutable.type]
<console>:11: error: illegal inheritance;
 self-type Foo does not conform to MutabilityLevel[Immutable.type]'s selftype MutabilityLevel[Immutable.type]
       class Foo extends MutabilityLevel[Immutable.type] with MutabilityLevel[Mutable.type]
                         ^
<console>:11: error: illegal inheritance;
 self-type Foo does not conform to MutabilityLevel[Mutable.type]'s selftype MutabilityLevel[Mutable.type]
       class Foo extends MutabilityLevel[Immutable.type] with MutabilityLevel[Mutable.type]

However..

scala> class Foo extends MutabilityLevel[Mutability]
defined class Foo