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

问题描述 投票:0回答:2

鉴于下面的示例,如何在不进行强制转换的情况下使代码编译

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)
    }
  }

}

谢谢。

scala generics pattern-matching scala-2
2个回答
0
投票

您可以尝试:

  • 创造一些证据,将你当前的类型转变为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
并没有那么糟糕。有时您无法避免它,因此最好创建一些小型的、经过良好测试的实用程序,这将有助于处理编译器不太智能的所有情况。


0
投票

这个怎么样:

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)
    }
  }

}
© www.soinside.com 2019 - 2024. All rights reserved.