我对Scala编程很新,所以仍然要找出做某事的规范方法。最近,我想编写一个函数foo
,它只接受一组类型的唯一参数。想想像
def foo(x: [Int, String]) = ???
但是我找不到任何接近上面语法的东西(我觉得这对我来说最自然)。使用类型Any
将导致编译端检查失败,并使问题更容易逃逸到运行时域。
我能想到的最好的是这样的:
sealed abstract class Base
case class TypeInt(v: Int) extends Base
case class TypeString(v: String) extends Base
implicit def toTypeInt(v: Int) = TypeInt(v)
implicit def toTypeString(v: String) = TypeString(v)
def foo(x: Base) = x match {
case TypeInt(v) => println("Int: ", v)
case TypeString(v) => println("String: ", v)
}
foo(1)
foo("hello")
(作为旁注,我希望能够只编写implicit case class ...
以避免手动创建toType*
函数但不编译。)
是否有更简单的方法来编写以类型安全的方式接受一组类型的参数的函数?
UPDATE :事实证明,在我的具体情况下,我可以使用方法重载。出于某种原因,在Scala工作表中根本不可能使用方法重载,这让我认为Scala根本没有超载。但我错了 - 在常规的Scala源代码中应该可以使用它。在下面的评论中提到的关于磁体模式的文章中仍然存在一些过载使用的缺点(例如,由于JVM泛型中的类型擦除,因此无法在类型Foo [Type1]和Foo [Type2]上重载。
答案 0 :(得分:4)
磁铁模式在这里感觉有些过分 - 您可以使用普通的旧类型:
trait Fooable[A] { def apply(a: A): Unit }
implicit object intFooable extends Fooable[Int] {
def apply(a: Int) = printf("Int: %d\n", a)
}
implicit object stringFooable extends Fooable[String] {
def apply(a: String) = printf("String: %s\n", a)
}
def foo[A: Fooable](a: A) = implicitly[Fooable[A]].apply(a)
然后:
scala> foo(1)
Int: 1
scala> foo("hello")
String: hello
假设您在擦除后担心碰撞。让我们尝试一些泛型类型的实例:
trait Bar[A]
implicit object barIntFooable extends Fooable[Bar[Int]] {
def apply(a: Bar[Int]) = println("A bar of ints.")
}
implicit object barStringFooable extends Fooable[Bar[String]] {
def apply(a: Bar[String]) = println("A bar of strings.")
}
再次:
scala> foo(new Bar[Int] {})
A bar of ints.
scala> foo(new Bar[String] {})
A bar of strings.
一切都按预期工作。