T <: A, return T method
Asked Answered
E

1

0

here is some sample code:

trait A
trait B extends A

def test[T <: A](): T = {
  new B {}
}

but I get an compile error:

type mismatch;
found   : B
required: T
new B {}

how to make it working ? ( but without doing asInstanceOf[T] at the end ) thanks!

Embow answered 5/10, 2020 at 13:25 Comment(1)
And what if I do trait C extends A and then I call test[C] (which is correct) and then it returns a B but I wanted a C?! - What is the meta-problem you want to solve; Since this looks like an xy-problem.Downhearted
P
6

The signature of your method

def test[T <: A](): T

promises that for any type T that is a subtype of A you return a value of this type T. And then you returned a value of type B. You violated the signature (there are many subtypes of A, not only B).

For example you can try a type class (in this way you say that you return a value of T not for any T <: A at all but for any T <: A that can be handled by the type class MakeT)

def test[T <: A]()(implicit makeT: MakeT[T]): T = makeT.makeT()

trait MakeT[T] { // or MakeT[+T]
  def makeT(): T
}

object MakeT {
  implicit val bMakeT: MakeT[B] = () => new B {}
  // or implicit def bMakeT[T >: B]: MakeT[T] = () => new B {}
}

test[B]().isInstanceOf[B] // true

In the situation described by @LuisMiguelMejíaSuárez in his comment

trait C extends A

you'll have

// test[C]() // doesn't compile, could not find implicit value for parameter makeT: MakeT[C]

Regarding generic return type see also

Why can't I return a concrete subtype of A if a generic subtype of A is declared as return parameter?

Type mismatch on abstract type used in pattern matching

Or you can use standard type classes =:=, <:<

def test[T <: A]()(implicit ev: B =:= T): T = {
  new B {}
}

(not implicit ev: T =:= B)

or

def test[T <: A]()(implicit ev: B <:< T): T = {
  new B {}
}
Peeling answered 5/10, 2020 at 14:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.