[英]Type mismatch with type parameters
我具有以下特征:
sealed trait Tree[+A]
case class Leaf[A](value: A) extends Tree[A]
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
然后,我定義一個類型為Branch
的變量:
val t = Branch(Branch(Leaf("S"), Leaf(2)), Leaf(99))
上面的代碼工作正常。 但是當我將其更改為:
val t = Branch[Int](Branch(Leaf("S"), Leaf(2)), Leaf(99))
編譯器抱怨:
Error:(41, 37) type mismatch;
found : String("S")
required: Int
val t = Branch[Int](Branch(Leaf("S"), Leaf(2)), Leaf(99))
當我確定第一個Branch
的類型(在這種情況下為Int)時,節點將是父節點固有的節點嗎?
此處發生的情況是,對於Branch(Leaf("S"), Leaf(2))
,編譯器將嘗試查找公用類型。 對於Int
和String
,它們的超類型將是Any
。
問題是您正在使用Branch[Int]
強制分支定義中的類型,該類型已由所包含的Branch[Any]
無效。 刪除[Int]
將解決編譯錯誤,但最終將導致Branch[Any]
。
讓我們細分一下您的定義:
sealed trait Tree[+A]
這里的+
表示類型A
可以是協變的。 我不會深入介紹方差,因為有很多很好的文章對此進行了解釋(例如, 此處 )。 基本上,這意味着如果String
是Any
的子類型,則Tree[String]
將是Tree[Any]
的子類型。
case class Branch[A](left: Tree[A], right: Tree[A]) extends Tree[A]
首先讓我們注意到A
在左側樹和右側樹中是如何出現的。 那么,當我們將兩棵具有不同類型的樹放入同一個分支時會發生什么呢?
val left = Leaf(1) // Tree[Int]
val right = Leaf("a") // Tree[String]
val tree = Branch(left, right) // Tree[???]
由於A
必須是在同一個left
和right
的值(這就是我們如何定義它),編譯器試圖解決這個問題。 因此它自問: Int
和String
的第一種常見類型是什么?
Any
^
/ \
/ \
/ \
AnyVal AnyRef
/ \
Int String
\ /
...
這是Scala中的類型層次結構相當簡化。 這里有更好的說明。 因此, String
和Int
的常見超類型是Any
,這就是為什么您的樹將成為Tree[Any]
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.