【问题标题】:Boilderplate-less Way to Upcast Scala Type Parameter to More General Trait将 Scala 类型参数向上转换为更通用特征的无样板方法
【发布时间】:2020-04-18 22:38:52
【问题描述】:

我有一个看起来像这样的场景:

trait T { }
class A extends T { }

class Container[T](val value: T) { } 

val valueFromElsewhere = new Container[A](new A())
val container: Container[T] = valueFromElsewhere

implicit def boilderplate(a: Container[A]): Container[T] = new Container[T](a.value)

我想使用valueFromElsewhere。它在一个容器中,容器的类型参数A按规范具有特征T。我只需要使用T的东西。

但是没有boilerplate,编译器不知道如何将Container[A] 转换为Container[T]。由于除了A 之外还有更多具有T 特征的类,我需要为它们中的每一个编写一个隐式转换。有没有更清洁的方法来做到这一点?

【问题讨论】:

  • 您所需要的只是协方差:class Container[+W](val value: W) { }
  • 没有协方差(这确实是更好的解决方案)你仍然不需要为T的每个子类型编写单独的转换:implicit def boilerplate(a: Container[_ <: T]): Container[T] = new Container[T](a.value)

标签: scala types


【解决方案1】:

根据@jwvh 和@Alexey Romanov 的建议,您可以使用这两种解决方案。

来自 jwvh

trait T
class A extends T

class Container[+W](val value: W)

val valueFromElsewhere = new Container[A](new A())
val container: Container[T] = valueFromElsewhere
//container: Container[T] = Container@69ba0e9

来自阿列克谢

trait T {}

case class A(a: Int) extends T {}

case class B(b: Int) extends T {}

class Container[T](val value: T) {}


object application extends App {
  implicit def boilderplate(a: Container[_ <: T]): Container[T] = new Container[T](a.value)

  val valueFromElsewhere = new Container[A](A(1))
  val valueFromElseWhere2 = new Container[B](B(2))
  val container: Container[T] = valueFromElsewhere
  val container1: Container[T] = valueFromElseWhere2
}

 println(container.value)
 println(container1.value)

【讨论】:

    猜你喜欢
    • 2023-04-01
    • 2022-12-11
    • 1970-01-01
    • 1970-01-01
    • 2023-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    相关资源
    最近更新 更多