2016-03-23 4 views
0

Ich frage mich, wie der Scala-Compiler (Version 2.11.7) Typinformationen über in einem Objekt definierte Typen (auch Typ Member) übergibt.Artinformationen von verschachtelten Typen beibehalten

Betrachten Sie diese Klassen:

trait Foo { 
    type Contents <: Any 
    val value: Contents 
    // Just a mock function call that uses a manifest. 
    def myCall(implicit mf: Manifest[Contents]): Contents = value 
} 

class Bar extends Foo { 
    type Contents = Int 
    val value = 20 
} 

class Baz extends Foo { 
    type Contents = String 
    val value = "it's baz" 
} 

Nun, wenn ich einen Anruf wie diese:

(new Bar).myCall 

Es funktioniert gut, und ich erhalte den Wert 20 zurückgegeben. In ähnlicher Weise wie dies ein Anruf tut auch funktioniert:

List(new Bar, new Bar).head.myCall 

In diesem Fall ich immer noch ein 20 zurückgegeben. Allerdings, wenn ich einen Anruf aus einer Liste von Foo s tun, so etwas wie diese:

List(new Bar, new Baz).head.myCall 

bekam ich einen Compiler-Fehler sagen, es nicht für den Anruf Manifest zur Verfügung steht. Meine Frage ist, ist es möglich, ein Manifest (oder TypeTag ~ es ist wirklich nicht wichtig) irgendwo, irgendwie, dass der Anruf oben funktioniert? Wenn das so ist, wie?

Antwort

1

In Ihrem zweiten Fall zugrunde liegende Typ Ihrer List ist ein Foo denn das ist der kleinste gemeinsame Typ für Bar und Baz ist. Dies bedeutet, dass der Kopf vom Typ Foo ist. Sie können Muster übereinstimmen, um den genauen Typ herauszufinden:

val maybeBar = List(new Bar, new Baz).head 
maybeBar match { 
    case b: Bar => println(b.myCall) // 20 
    case b: Baz => println(b.myCall) // it's baz 
    case _ => println("?") 
} 
+0

Vielen Dank. Dies erfordert jedoch, Bar und Baz im Voraus zu kennen. Gibt es eine Möglichkeit, es zum Laufen zu bringen, wenn wir nicht wissen, womit "Foo" erweitert wird? – bow

+0

Matching auf "einige T, die Foo erweitert" wird nicht funktionieren, wie Sie wissen. Es gibt noch eine andere Möglichkeit, die strukturelle Typisierung (auch bekannt als Duck-Typing), die besagt, dass "Muster mit einem Typ übereinstimmt, der eine Methode myCall hat". Ich denke jedoch nicht, dass Sie das richtige Manifest auf diese Weise injizieren können, aber ich kann mich irren (strukturelle Typisierung ist Typakrobatik, mit der ich nicht viel Erfahrung habe). Siehe http://stackoverflow.com/questions/1988181/pattern-matching-structural-types-in-scala – slouc

Verwandte Themen