Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I restrict types in overridden method in Scala?

trait Rendered
trait TemplateRendered extends Rendered
trait Media {
  def send[T <: Rendered](cooked:T)
}
case class EmailMedia() extends Media {
  override def send(cooked:TemplateRendered) {}  // compile error this line
}

I want to have a Media template with a send() method that accepts a subclass Rendered object. In the concrete classes (EmailMedia) I want to lock that down to a particular subclass of Rendered, or TemplateRendered in this case. (i.e. make the type in the class more restrictive/specific than the type in the trait)

How can I do that?

The attempt here wasn't liked by the compiler. Tried this too:

case class EmailMedia() extends Media {
  override def send[T <: TemplateRendered](cooked:T) {}
}
like image 674
Greg Avatar asked Sep 21 '15 13:09

Greg


1 Answers

How about:

trait Rendered
trait TemplateRendered extends Rendered

trait Media[T <: Rendered] {
  def send(cooked: T): Unit
}

case class EmailMedia() extends Media[TemplateRendered] {
  override def send(cooked: TemplateRendered): Unit = {}
}

Do you expect Media to provide more than one generic method? If that is the case, you might consider moving that generic parameter to a type member to keep things a bit more readable:

trait Rendered
trait TemplateRendered extends Rendered
trait BazzRendered extends Rendered

trait Media {
  type SendRend <: Rendered
  type FooRend <: Rendered

  def send(cooked: SendRend): Unit
  def foo(bar: FooRend): Unit
}

case class EmailMedia() extends Media {
  type SendRend = TemplateRendered
  type FooRend = BazzRendered

  override def send(cooked: SendRend): Unit = {}
  override def foo(bar: FooRend): Unit = {}
}
like image 195
falconepl Avatar answered Oct 15 '22 02:10

falconepl