scala 我如何从一个具有泛型、有界类型的方法返回一个类型的子类?

3xiyfsfu  于 12个月前  发布在  Scala
关注(0)|答案(2)|浏览(102)

在下面的例子中,我怎样才能使代码编译而不求助于myMethod中的强制转换?

object Test {
  sealed trait MyTrait
  case class A(v: Int) extends MyTrait
  case class B(v: Int) extends MyTrait

  def myMethod[T <: MyTrait](in0: T): T = {
    in0 match {
      case in: A => in.copy(v = 1)
      case in: B => in.copy(v = 2)
    }
  }

}

谢谢.

xytpbqjk

xytpbqjk1#

您可以尝试:

  • 创建一些证据,将您当前的类型转换为T
  • identity启动它
  • 让Scala
  • 一方面调整输入类型,使其与in值相同
  • 把这些证据和

例如,您可以像这样实现它

import scala.annotation.nowarn

sealed trait MyTrait
case class A(v: Int) extends MyTrait
case class B(v: Int) extends MyTrait

@nowarn
def myMethod[T <: MyTrait](in0: T): T = {
  case class IntoT[A, B](value: A, upcast: A => B)
  IntoT(in0, identity[T]) match {
    case IntoT(in : A, upcastA: (A => T)) => upcastA(in.copy(v = 1))
    case IntoT(in : B, upcastB: (B => T)) => upcastB(in.copy(v = 2))
  }
}

它将使不匹配的类型错误消失。相反,你会得到警告,

match may not be exhaustive.

It would fail on pattern case: IntoT(_, _)

这又可以用@nowarn来抑制。
然而,老实说,在这种情况下,当我知道我比编译器更了解时-因为代码是微不足道的,一目了然,我也用测试来覆盖它-.asInstanceOf并没有那么糟糕。有时你无法避免它,所以最好创建一些小的,经过良好测试的实用程序,这将有助于处理编译器不那么聪明的所有情况。

gfttwv5a

gfttwv5a2#

this one

object Test {
  sealed trait MyTrait[T]{
    def copy(v: Int): T
  }
  case class A(v: Int) extends MyTrait[A]
  case class B(v: Int) extends MyTrait[B]

  def myMethod[T <: MyTrait[T]](in0: T): T = {
    in0 match {
      case _: A => in0.copy(v = 1)
      case _: B => in0.copy(v = 2)
    }
  }

}

another solution

object Test {
  
  trait MyTrait
  case class A(v: Int) extends MyTrait
  case class B(v: Int) extends MyTrait

  import scala.language.reflectiveCalls
  def myMethod[T <: MyTrait](in: {def copy(v: Int): T}): T = in match {
      case _: A => in.copy(v = 1)
      case _: B => in.copy(v = 2)
  }
  val a: A = myMethod(A(1))
    val b: B = myMethod(B(2))
}

相关问题