【发布时间】:2015-10-07 00:49:50
【问题描述】:
基本上,我想做的是为自定义类编写“map”的重载版本,这样每个版本的 map 仅因传递给它的函数类型而异。
这是我想做的:
object Test {
case class Foo(name: String, value: Int)
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map(func: Int => Int) = Foo(f.name, func(f.value))
def map(func: String => String) = Foo(func(f.name), f.value)
}
def main(args: Array[String])
{
def square(n: Int): Int = n * n
def rev(s: String): String = s.reverse
val f = Foo("Test", 3)
println(f.string)
val g = f.map(rev)
val h = g.map(square)
println(h.string)
}
}
当然,由于类型擦除,这是行不通的。任何一个版本的地图都可以单独工作,它们可以命名不同,一切正常。但是,用户可以简单地根据传递给它的函数类型调用正确的映射函数,这一点非常重要。
在寻找如何解决这个问题的过程中,我发现了 TypeTags。这是我想出的代码,我认为它接近正确,但当然不太有效:
import scala.reflect.runtime.universe._
object Test {
case class Foo(name: String, value: Int)
implicit class FooUtils(f: Foo) {
def string() = s"${f.name}: ${f.value}"
def map[A: TypeTag](func: A => A) =
typeOf[A] match {
case i if i =:= typeOf[Int => Int] => f.mapI(func)
case s if s =:= typeOf[String => String] => f.mapS(func)
}
def mapI(func: Int => Int) = Foo(f.name, func(f.value))
def mapS(func: String => String) = Foo(func(f.name), f.value)
}
def main(args: Array[String])
{
def square(n: Int): Int = n * n
def rev(s: String): String = s.reverse
val f = Foo("Test", 3)
println(f.string)
val g = f.map(rev)
val h = g.map(square)
println(h.string)
}
}
当我尝试运行此代码时,出现以下错误:
[error] /src/main/scala/Test.scala:10: type mismatch;
[error] found : A => A
[error] required: Int => Int
[error] case i if i =:= typeOf[Int => Int] => f.mapI(func)
[error] ^
[error] /src/main/scala/Test.scala:11: type mismatch;
[error] found : A => A
[error] required: String => String
[error] case s if s =:= typeOf[String => String] => f.mapS(func)
func 的类型确实是 A => A,那么如何告诉编译器我在运行时匹配了正确的类型?
非常感谢。
【问题讨论】:
标签: scala functional-programming overloading type-erasure