Question

I have the following class hierarchy:

trait Entity {
  type E <: Entity
  type S <: Something[E]
  def in: S
}

trait Something[E <: Entity] {
  def doSomething {
    // something
  }
}

class A extends Entity {
  def in = InA
  object InA extends Something[A]
}
class B extends Entity {
  def in = InB
  object InB extends Something[B]
}
class C extends Entity {
  def in = InC
  object InC extends Something[C]
}

and somewhere else I want to:

val entities = Seq[Entity]
entities.map(_.in.doSomething)

however, the type system does not let me get away with that in method definition - I just can't figure out what types should I specify there for the piece of code to work?

Was it helpful?

Solution

It works if you override the type members like this. Scala does not infer them automatically.

class A extends Entity {
  type E = A
  type S = Something[A]
  def in = InA
  object InA extends Something[A]
}
class B extends Entity {
  type E = B
  type S = Something[B]
  def in = InB
  object InB extends Something[B]
}
class C extends Entity {
  type E = C
  type S = Something[C]
  def in = InC
  object InC extends Something[C]
}

Another option would be to do away with type members and only use type parameters.

trait Entity[E <: Entity[E]] {
  def in: Something[E]
}

trait Something[E <: Entity[E]] {
  def doSomething {
    // something
  }
}

class A extends Entity[A] {
  def in = InA
  object InA extends Something[A]
}
class B extends Entity[B] {
  def in = InB
  object InB extends Something[B]
}
class C extends Entity[C] {
  def in = InC
  object InC extends Something[C]
}

val entities = Seq[Entity[_]]()
entities.map(_.in.doSomething)

This uses a technique called F-bounded polymorphism.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top