Scala:重载(Seq [T])和(T *)

时间:2012-09-20 12:27:18

标签: scala types overloading type-erasure

我有一个案例类,将Seq [T]作为参数:

case class MyClass(value: Seq[T])

我现在希望能够写

MyClass(t1,t2,t3)

所以我定义了

object MyClass {
    def apply(value: T*) = new MyClass(value.toSeq)
}

它不起作用,因为案例类定义了

object MyClass {
    def apply(value: Seq[T])
}
擦除后,

和Seq [T]和T *具有相同的类型,因此我不能超载它们。

但我想允许两种访问方式。应该允许这两种方式:

MyClass(t1,t2,t3)
MyClass(some_seq_of_T)

由于Seq [T]和T *几乎是相同的类型(至少在擦除之后;并且在具有参数T *的函数内部变为Seq [T]),我认为应该有一种方法允许两种方式叫它。

有吗?

3 个答案:

答案 0 :(得分:6)

你可以作弊并定义你的同伴:

case class MyClass[T](value: Seq[T])

object MyClass {
  def apply[T](first: T, theRest: T*) = new MyClass(first :: theRest.toList)
  def apply[T]() = new MyClass[T](Nil)
}

只要至少有一个参数,第一个apply就会处理MyClass(1,2,3)。 scond apply处理0参数的情况。它们与常规构造函数不冲突。

这样您就可以撰写MyClass(Seq(1,2,3))MyClass(1,2,3)MyClass()。请注意,对于空的,你必须告诉它要返回什么类型,否则它会假设MyClass[Nothing]

答案 1 :(得分:3)

这是没有案例类的解决方案:

scala> class A[T] (ts: Seq[T]) { def this(ts: T*)(implicit m: Manifest[T]) = this(ts) }
defined class A

scala> new A(1)
res0: A[Int] = A@2ce62a39

scala> new A(Seq(1))
res1: A[Seq[Int]] = A@68634baf

答案 2 :(得分:0)

不能有两个同名的方法,其中一个方法采用Seq[T]类型的参数,一个采用T*。编译器如何知道是否像

这样的调用
val s = Seq(1,2,3) 
foo(s)

应该调用第一个方法或第二个方法(使用T = Int)或第二个方法(使用T = Seq [Int])?