John Sullivan
John Sullivan

Reputation: 1311

Scala trait method restricted to implementing type

So I'm having some trouble with what I think is a pretty simple situation in trait implementation, and I'm hoping there is some simple solution that I'm missing. I'd like to have a method on a trait that accepts as a parameter (and returns as a value only the type of the concrete implementation that it is being called on. Specifically:

trait Foo {
  type ConcreteFoo // what to put here?
  def combine(that:ConcreteFoo):ConcreteFoo
}

class FooImpl1 extends Foo {
  def combine(that:FooImpl1):FooImpl1 = {
    // implementation
  }
}

class FooImpl2 extends Foo {
  def combine(that:FooImpl2):FooImpl2 = {
    // implementation
  }
}

Right now I have a type Self = FooImpl on the implementing classes, but I'd rather have something on the trait that takes care of it if possible.

Upvotes: 1

Views: 287

Answers (2)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

This is exactly F-Bounded Polymorphism:

trait Foo[T <: Foo[T]]
  def combine(that: T): T
}

class FooImpl1 extends Foo[FooImpl1] {
  def combine(that: FooImpl1): FooImpl1 = {
    ???
  }
}

class FooImpl2 extends Foo[FooImpl2] {
  def combine(that: FooImpl2): FooImpl2 = {
    ???
  }
}

Upvotes: 3

Tyler
Tyler

Reputation: 18177

You can add a type parameter to your trait like this:

trait Foo[A] {
    def combine(that: A): A
}

class FooImpl1 extends Foo[FooImpl1] {
    override def combine(that: FooImpl1): FooImpl1 = ???
}

class FooImpl2 extends Foo[FooImpl2] {
    override def combine(that: FooImpl2): FooImpl2 = ???
}

Upvotes: 0

Related Questions