2014-05-02 24 views
1

我可以理解爲什麼下面的代碼不能被編譯:無法明白爲什麼`性狀你好[+ A] {DEF測試[B <:A]}`不能被編譯

trait Hello[+A] { 
    def test[B<:A](x: B) 
} 

因爲:

val child: Hello[String] = new Hello[String] { 
    def test[B <: String](x: B) = x.substring(1) 
} 
val parent: Hello[Any] = child 
parent.test(123) // child.test can't handle integer 

但我不明白爲什麼好下面的代碼不能被編譯:

trait Hello[+A] { 
    def test[B<:A] 
} 

不同的是後來的一個沒有參數,我們不能將任何值傳遞給test方法。

爲什麼編譯器仍然認爲它是無效的?

回答

4

當你試圖在REPL做它,它說:

scala> trait Hello[+A] { 
    |  def test[B<:A](x: B) 
    | } 
<console>:8: error: covariant type A occurs in contravariant position in type <: A of type B 
      def test[B<:A](x: B) 
        ^

理當如此。想象一下,如果這是可能的,你可以:

val x:Hello[Dog] = new Hello[Dog]{..} 
val y:Hello[Animal] = x 
y.test(Cat)//Oops 

關於參數,是什麼讓你覺得它沒有任何參數使它安全。你可以使用說implicitly得到變量,並做危險的東西,編譯器不會阻止你。例如:

def test[B<:A]:B = this 
+0

示例'def test [B <:A]:B = this'不好。實際上,B是不變的,它可能出現在返回式位置。參見compilable的例子:'特質貓[-A] {def meow [B <:A](x:B):B}' – Freewind

+0

我認爲原因是'B'可以從參數推斷出來,但也可以指定。所以'val parent:Hello [Any] = child; parent.test [Any]',我們可以將'Any'指定爲'test',但不是'String'的子類型。 – Freewind

相關問題