2012-05-23 47 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