Search code examples
oopscalatype-systems

Extending a generic type


I am stuck with a "simple" problem. I am working with files metadata. I would like to provide both a read-only view (trait ReadOnly) with just getters as well as a read-write view (trait ReadWrite) with getters and setters. Each read-write view must extend a read-only view.

trait ReadOnly 

trait ReadWrite

trait BasicRO extends ReadOnly {
  def foo: String
  def bar: Int
}

class BasicRW extends ReadWrite with BasicRO {
  def foo: String = ???
  def foo_=( str: String ): Unit = ???
  def bar: Int = ???
  def bar_=( i: Int ): Unit = ???
}

So far so good. But now, I would like to add a snapshot method to ReadWrite which will return the corresponding ReadOnly view (the same that was extended by the ReadWrite sub-class). In pseudo-scala, I would like to define this constraint as:

trait ReadWrite[T <: ReadOnly] extends T {
  def snaphsot: T
} 

But it does not compile because class type required but T found (compiler message). Is there a way to express this constraint in the Scala type-system ?


Solution

  • Just to be clear, you want snapshot to be in a separate trait, but it can only be used in a class which also extends ReadOnly?

    You can use a self type for this

    trait ReadOnly[T]
    
    trait ReadWrite[T] { self: ReadOnly[T] => 
       def snapshot: T
    }
    
    trait BasicRO[T] extends ReadOnly[T] {
      def foo: String
      def bar: Int
    }
    
    abstract class class1[T] extends ReadOnly[T] with ReadWrite[T]  // legal
    
    abstract class class2[T] extends ReadWrite[T] // Not legal
    
    abstract class class3[T] extends BasicRO[T] with ReadWrite[T] // legal
    

    This doesn't make ReadWrite extend ReadOnly, but it both requires that the base object also mix in a ReadOnly (with the same type parameter) and gives ReadWrite access to ReadOnly's methods, while allowing the two traits to be subclassed entirely independently of eachother.