2016-08-11 4 views
2

Dies scheint eine einfache Sache, aber ich kann es nicht verstehen ...Sammlung Strukturtyp Parameter Seltsamkeit

Dies kompiliert:

object CanFoo1 { 
    def foo(): Unit = { 
    println("Yup, I can foo alright") 
    } 
} 

object CanFoo2 { 
    def foo(): Unit = { 
    println("And I can foo with the best") 
    } 
} 

trait A { 
    type CanFoo = { def foo(): Unit } 
    def fooers: Seq[CanFoo] 
} 

class B extends A { 
    def fooers = Seq(
    // CanFoo1, // <- won't compile when this is uncommented 
    CanFoo2 
) 
} 

Aber uncommenting die // CanFoo1, Linie gibt:

error: type mismatch; 
found : Seq[Object] 
required: Seq[B.this.CanFoo] 
    (which expands to) Seq[AnyRef{def foo(): Unit}] 
def fooers = Seq(
      ^
one error found 

So scheint es, dass der Compiler versteht, dass eine Sammlung mit nur einem Element Seq(CanFoo2) (oder Seq(CanFoo1)) vom richtigen Typ ist, aber wenn beide Objekte in der Sammlung sind, gibt es auf? Was mache ich hier falsch?

Antwort

2

So scheint es, wie der Compiler versteht, dass eine Sammlung nur ein Element Seq(CanFoo2) (oder Seq(CanFoo1)) mit dem korrekten Typ ist, aber wenn beiden Objekte in der Sammlung sind gibt es auf? Was bin ich? Ich mache hier falsch?

Wenn Sie CanFoo1 oder CanFoo2 zum Seq passieren gelten, wird die Sequenz abgeleitet CanFoo1.type oder CanFoo2.type vom Typ jeweils zu sein, ist es nicht abgeleitet von CanFoo Typ sein.

Wenn Sie in beiden Elementen zum Seq passieren, versucht der Compiler für einen gemeinsamen Typ zu suchen, auf die sie wirksam ableiten kann, um den Code der Kompilierung zu machen, und die einzige Art es finden kann, ist Object, aber fooers soll vom Typ Seq[CanFoo] sein, so schreit der Compiler.

Sie können den Compiler ein wenig helfen, indem sie ausdrücklich die Art der Sammlung zu schreiben:

class B extends A { 
    def fooers = Seq[CanFoo](
    CanFoo1, 
    CanFoo2 
) 
} 
+0

Danke für die schnelle und informative Antwort. Ich glaube, ich verstehe jetzt - ohne einen expliziten Typparameter wird der Collection-Typ aus den Elementen abgeleitet, und dann wird dieser abgeleitete Typ auf die Konformation zum Strukturtyp überprüft. Der Typinferenzierer enthält den deklarierten Strukturtyp nicht in den Dingen, die er beim Ableiten des Typs von Seq kennt. – delocalizer