2014-05-02 1 views
1

Je peux comprendre pourquoi le code suivant ne peut pas être compilé:ne comprends pas pourquoi trait `Bonjour [+ A] {tester def [B <: A]}` ne peut pas être compilé

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

Parce que:

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 

Mais je ne comprends pas bien pourquoi le code suivant ne peut pas être compilé:

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

la différence est celle qui plus tard ne pas les paramètres, nous ne peut pas transmettre de valeur à la méthode test.

Pourquoi le compilateur pense toujours qu'il n'est pas valide?

Répondre

4

Lorsque vous essayez de le faire dans rempl, il dit:

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) 
        ^

à juste titre. Imaginez si cela était possible et vous pourriez:

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

À propos des paramètres, qu'est-ce qui vous fait penser qu'il est sûr sans aucun argument. Vous pouvez obtenir la variable en utilisant implicitly et faire des choses dangereuses, ce compilateur ne vous arrêtera pas. Exemple:

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

L'exemple 'def test [B <: A]: B = this' n'est pas bon. En fait, B est invariant, il peut apparaître dans la position de type retour. Voir l'exemple compilable: 'trait Cat [-A] {def miaou [B <: A] (x: B): B}' – Freewind

+0

Je pense que la raison est que 'B' peut être déduit du paramètre, mais peut aussi être spécifié . Donc 'val parent: Bonjour [Tout] = enfant; parent.test [Any] ', nous pouvons spécifier' Any' à 'test', mais ce n'est pas le sous-type de' String'. – Freewind

Questions connexes