2013-08-18 32 views
2

我对Scala编程颇为陌生,所以仍然想出了执行某些操作的规范方法。最近,我想编写一个函数foo,它只接受一组参数的类型。想想类似在Scala中模拟函数过载

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]。

+3

您正试图重新发明[磁铁模式](http://spray.io/blog/2012-12-13-the-magnet-pattern/) –

+0

谢谢 - 我会读取该链接。 –

+1

@AlexeyAlexandrov:你应该将你的“更新”移到答案上,并接受它来标记你的问题为答案。 – senia

回答

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. 

一切。