Scala:通用方法隐式参数
Scala : Generic method implicit parameter
我遇到了一个代码片段,但无法理解它。片段是:
implicit val dummyVisit = Visit("", 1L, 1, 1, 1, 1L)
implicit val dummyOrder = Order("", 1L, 1, 1, 1, 1L)
def process[T](events : Array[T])(implicit t: T):Unit = {
println(t)
if(!events.isEmpty)
t match {
case r: Order => processOrder(events.asInstanceOf[Array[Order]])
case r: Visit => processVisit(events.asInstanceOf[Array[Visit]]);
}
}
def processOrder(arr: Array[Order]): Unit = { println(arr.size) }
def processVisit(arr: Array[Visit]): Unit = { println(arr.size) }
implicit
变量 t
,需要 dummyVisit
和 dummyOrder
存在。
问题:
这是implicit parameter
的正确使用方式吗?
有没有更好的方法在不使用隐式参数的情况下获取 T
的 class 类型?
捕获参数的类型是隐式参数的预期用途之一。
虽然我会写一些不同的东西:
import scala.reflect.ClassTag
// `sealed` ensures that no extra evidences can be defined elsewhere
sealed abstract class Evidence[T](implicit val tag: ClassTag[T])
object Evidence {
implicit object visitEvidence extends Evidence[Visit]
implicit object orderEvidence extends Evidence[Order]
}
def process[T](events: Array[T])(implicit ev: Evidence[T]) = {
import ev.tag // import ClassTag[T] to allow matching on array element types
events match {
case Array() => // don't process empty arrays
case arr: Array[Order] => processOrder(arr)
case arr: Array[Visit] => processVisit(arr)
}
}
此代码避免创建无意义的虚拟实例,并避免使用 asInstanceOf
进行类型转换。
更进一步是在隐式参数中捕获处理操作本身,并完全避免每种情况下的显式 match
。这也称为 typeclass 模式:
sealed trait ProcessArray[T] {
def apply(arr: Array[T]): Unit
}
object ProcessArray {
implicit object processVisitArray extends ProcessArray[Visit] {
def apply(arr: Array[Visit]) = { println(arr.size) }
}
implicit object processOrderArray extends ProcessArray[Order] {
def apply(arr: Array[Order]) = { println(arr.size) }
}
}
def process[T](array: Array[T])(implicit proc: ProcessArray[T]) = {
if (array.nonEmpty) proc(array)
}
我遇到了一个代码片段,但无法理解它。片段是:
implicit val dummyVisit = Visit("", 1L, 1, 1, 1, 1L)
implicit val dummyOrder = Order("", 1L, 1, 1, 1, 1L)
def process[T](events : Array[T])(implicit t: T):Unit = {
println(t)
if(!events.isEmpty)
t match {
case r: Order => processOrder(events.asInstanceOf[Array[Order]])
case r: Visit => processVisit(events.asInstanceOf[Array[Visit]]);
}
}
def processOrder(arr: Array[Order]): Unit = { println(arr.size) }
def processVisit(arr: Array[Visit]): Unit = { println(arr.size) }
implicit
变量 t
,需要 dummyVisit
和 dummyOrder
存在。
问题:
这是
implicit parameter
的正确使用方式吗?有没有更好的方法在不使用隐式参数的情况下获取
T
的 class 类型?
捕获参数的类型是隐式参数的预期用途之一。
虽然我会写一些不同的东西:
import scala.reflect.ClassTag
// `sealed` ensures that no extra evidences can be defined elsewhere
sealed abstract class Evidence[T](implicit val tag: ClassTag[T])
object Evidence {
implicit object visitEvidence extends Evidence[Visit]
implicit object orderEvidence extends Evidence[Order]
}
def process[T](events: Array[T])(implicit ev: Evidence[T]) = {
import ev.tag // import ClassTag[T] to allow matching on array element types
events match {
case Array() => // don't process empty arrays
case arr: Array[Order] => processOrder(arr)
case arr: Array[Visit] => processVisit(arr)
}
}
此代码避免创建无意义的虚拟实例,并避免使用 asInstanceOf
进行类型转换。
更进一步是在隐式参数中捕获处理操作本身,并完全避免每种情况下的显式 match
。这也称为 typeclass 模式:
sealed trait ProcessArray[T] {
def apply(arr: Array[T]): Unit
}
object ProcessArray {
implicit object processVisitArray extends ProcessArray[Visit] {
def apply(arr: Array[Visit]) = { println(arr.size) }
}
implicit object processOrderArray extends ProcessArray[Order] {
def apply(arr: Array[Order]) = { println(arr.size) }
}
}
def process[T](array: Array[T])(implicit proc: ProcessArray[T]) = {
if (array.nonEmpty) proc(array)
}