5

我有一个案例类,以 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]),我认为应该有一种方法可以允许两种方式调用它.

在那儿?

4

3 回答 3

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)scondapply处理 0 参数的情况。它们与常规构造函数不冲突。

这样您就可以编写MyClass(Seq(1,2,3)),MyClass(1,2,3)MyClass(). 请注意,对于空的,您必须告诉它要返回的类型,否则它将假定为MyClass[Nothing]

于 2012-09-20T12:48:20.937 回答
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
于 2012-09-20T13:01:09.437 回答
0

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

val s = Seq(1,2,3) 
foo(s)

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

于 2012-09-20T12:37:15.160 回答