2012-05-23 42 views
1

我使用的Scala 2.9Scala的重复参数和参数列表混乱

我有一个类:

class Queue[T] private(private val heading: List[T], private val trailing: List[T]) { 
     def this(a: T*) = this(a.toList, Nil) 

     private def mirror = { 
      if (heading.isEmpty) { 
       new Queue[T](trailing.reverse, Nil) 
      } else this 
     } 

     def head = { 
      val q = mirror 
      if (q.heading.isEmpty) None else new Some(q.heading.head) 
     } 

     def tail = { 
      val q = mirror 
      if (q.heading.isEmpty) q else new Queue[T](q.heading.tail, trailing) 
     } 

     def enqueue(a: T) = { 
      new Queue[T](heading, a::trailing) 
     } 
    } 

在方法排队,如果我写new Queue(heading, a::trailing)(留出类型参数[T] ),代码将不会编译和scalac投诉有关“模糊引用重载的定义,类Queue类(队列类型(T *)队列[T]和构造函数Queue类Queue类型(标题:列表[ T],尾随:List [T])队列[T]匹配参数类型(List [T],List [T])“)。

那么为什么有必要明确指定类型参数[T]否则Scala会将两个单独的列表作为一个整体对待重复参数?我认为这与类型推断有关,有人可以解释吗?

回答

2

如果您不提供类型参数,编译器可以推断出T(对于主构造函数)或List[T](对于辅助构造函数)。

+0

谢谢你Heiko。显然我没有意识到辅助构造函数可以用于T = List [U]的2 List [U]。 – digizer0

2

顶尖舞者的答案是正确的,但要澄清这一点,在enqueueT比一个在Queue的背景下,不同T您要创建并具有因此可以推断出这导致了歧义。为什么你有2个构造函数呢?我建议你为你的外部世界的构造函数使用同伴:

class Queue[T] private(private val heading: List[T], private val trailing: List[T]) { /* ... */} 

object Queue { 
    def apply[T](xs: T*) = new Queue(xs.toList, Nil) 
} 
+0

谢谢drexin。我不完全理解你的观点,即队列中的T与队列中的队列T不同,我认为队列中的T和队列中的T相同,这就是为什么'a :: trailing'不会给出错误的原因。而且我最好让Queue成为特质,并将对象当作外部世界的工厂。感谢您的建议。 – digizer0

+0

“新队列”中的“T”未指定,因此编译器试图推断它。由于您有两个与您的List [T],List [T]'构造函数匹配的构造函数,因此编译器无法推断出您要调用的构造函数。当你明确地从你当前的上下文中传入'T'时,编译器知道新实例的'T'应该是你的旧'T'而不是'List [T]'。 – drexin

+0

我现在明白了。非常感谢你。 – digizer0