scala - AnyVal 类型的 AnyRef 等效项
问题描述
给定一个类型T
,是否有一种惯用的 Scala 方式来描述(我们称之为)的AnyRef
等价物。例如,T
ARE[T]
ARE[T <: AnyRef]
是T
ARE[T <: AnyVal]
相当于java.lang.*
存在T
时或不存在时出现编译错误
该问题的目的是允许实现许多方法,例如:
def foo[A](...): ARE[A]
同时避免 Boolean、Byte、Char、Double、Float、Int、Long 和 Short 的幼稚def foo[A <: AnyRef](...): A
+ 重载。
解决方案
实现这样的类型计算的标准方法是创建一个类型类:
sealed trait Box[T] {
type Out
def apply(t: T): Out
}
object Box {
type Aux[T, ARE] = Box[T] { type Out = ARE }
def make[T, ARE](f: T => ARE): Box.Aux[T, ARE] = new Box[T] {
type Out = ARE
def apply(t: T) = f(t)
}
implicit val int: Box.Aux[Int, java.lang.Integer] = make(Int.box)
implicit val long: Box.Aux[Long, java.lang.Long] = make(Long.box)
implicit val short: Box.Aux[Short, java.lang.Short] = make(Short.box)
implicit val byte: Box.Aux[Byte, java.lang.Byte] = make(Byte.box)
implicit val char: Box.Aux[Char, java.lang.Character] = make(Char.box)
implicit val float: Box.Aux[Float, java.lang.Float] = make(Float.box)
implicit val double: Box.Aux[Double, java.lang.Double] = make(Double.box)
implicit val boolean: Box.Aux[Boolean, java.lang.Boolean] = make(Boolean.box)
implicit val unit: Box.Aux[Unit, scala.runtime.BoxedUnit] = make(Unit.box)
implicit def anyRef[T <: AnyRef]: Box.Aux[T, T] = make(identity)
def box[T](t: T)(implicit are: Box[T]): are.Out = are(t)
}
这可以像任何其他类型类一样使用。例如,您可以ARE
借助Box.Aux
自己的函数计算类型:
def box2[T, ARE](t: T)(implicit box: Box.Aux[T, ARE]): ARE = box(t)
Scala 接受预期时间Box.box
的输出:AnyRef
scala> def foo[T <: AnyRef](anyRef: T): T = anyRef
foo: [T <: AnyRef](anyRef: T)T
scala> foo(10)
<console>:13: error: inferred type arguments [Int] do not conform to method foo's type parameter bounds [T <: AnyRef]
foo(10)
^
<console>:13: error: type mismatch;
found : Int(10)
required: T
foo(10)
^
scala> foo(Box.box(10))
res1: Box.int.Out = 10
Scala 也知道ARE
从返回的确切类型Box.box
:
scala> def bar[T](t: T)(implicit ev: T =:= java.lang.Integer) = ev
bar: [T](t: T)(implicit ev: =:=[T,Integer])=:=[T,Integer]
scala> bar(10)
<console>:13: error: Cannot prove that Int =:= Integer.
bar(10)
^
scala> bar(Box.box(10))
res2: =:=[Box.int.Out,Integer] = <function1>
推荐阅读
- html - 在 2 列中的列表之间添加水平空间以使其居中
- javascript - 对象变量在括号中呈现,而不仅仅是预期的内容
- spring - 如何使用spring和restful服务在单个请求正文中发布多部分内容类型
- java - 在 jsonb 数组列中搜索匹配项
- javascript - React 中的类型是什么?
- python-2.7 - UnboundLocalError:分配前引用的局部变量“out” - durnig 训练模型
- python - 模型应该包含哪些方法
- python - 用反斜杠替换双反斜杠
- angular - 如何使用 Angular 中的单击按钮放大某个位置
- tableau-api - Tableau 包含查询