[EDITED BELOW]Abgeleitete Klassen als Klassen Konstruktorparameter
Ich habe eine Klassenhierarchie, die, gerade jetzt ist, etwa wie folgt:
sealed trait Foo {
def method: Any
}
case class Bar extends Foo {
def method: Array[String] = // implementation
}
case class Baz extends Foo {
def method: Map[String, Array[String]] = // implementation
}
Ich bin die abstrakte Methode einen Rückgabetyp von Any
geben weil die Rückgabetypen der Fallklassen notwendigerweise unterschiedlich sind, aber sie haben einen ähnlichen Zweck. Aus diesem Grund möchte ich es behalten, dieses übliche Verhalten zu modellieren, und dies ist die einzige Möglichkeit, die ich gefunden habe, um es kompilieren zu lassen. Mir ist klar, dass dies gegen den Geist von Scalas Typsystem ist, also stelle ich die erste Frage unten.
Dann erwartet eine weitere Klasse eine Unterklasse von Foo
als Konstrukteur Parameter, und ich weiß nicht, wie dies zu bezeichnen, andere als die folgenden:
class Qux(foo: Foo) {
val m = foo.method
...
...
}
Später in der Klasse Qux
es Methoden gibt, die erwarten die val m
des Typs an die jeweiligen Unterklasse (Bar
oder Baz
) von Foo
entsprechend zu sein, aber ich bin immer Kompilierungsfehlern wie
... type mismatch;
[error] found : Any
[error] required: Array[String]
Also habe ich ein paar Fragen:
- ich mit Scala vertraut genug bin zu glauben, dass dies der richtige Weg ist mein besonderes Problem darstellen, aber nicht vertraut genug mit ihm zu wissen, wie man das macht. Was ist der richtige Weg, um das zu tun, was ich versuche?
- Auch ist es eine Möglichkeit, Klasse sagen
Qux
dassm
sollte durch die spezifischemethod
vonBar
oderBaz
und nicht die abstrakte Methode vonFoo
zurück als Wert behandelt werden?
Edit: den Ansatz von @marios vorgeschlagen Taking (abstrakte Elemente vom Typ verwendet wird) scheint ein Schritt in die richtige Richtung zu sein, aber ein Typenkonflikt erscheint jetzt auf. Innerhalb der Klasse Qux
, ich habe jetzt
class Qux[X <: Foo](sc: SparkContext, val foo: X) {
val m: foo.A = foo.method
def process(rows: DataFrame) = foo match {
case Bar(sc, _) => BarProcessor(sc, m).doStuff(rows)
case Baz(sc, _) => BazProcessor(sc, m.keys).doStuff(rows, m.values)
}
}
Wo BarProcessor
mit instanziiert wird zum Beispiel eine Array[String]
und BazProcessor
braucht, um die Schlüssel-Wert-Paare aus dem Rückgabewert von Baz
‚s method
Sachen zu tun. Allerdings bin ich jetzt Fehler wie
[error] Qux.scala:4: type mismatch;
[error] found : Qux.this.foo.A
[error] required: Array[String]
[error] case Bar(sc, _) => BarProcessor(sc, m).doStuff(rows)
[error] ^
Ähnliche Fehler zeigen sich immer, wenn ich versuche Map
-spezifische Methoden auf m
zu rufen, wenn foo
ist ein Baz
(entlang der Linien von value keys is not a member of Qux.this.foo.A
, etc.). Ich verstehe, dass m
ist nicht wirklich ein Array[String]
- es ist vom Typ A
. Aber gibt es eine Möglichkeit, Scala zu sagen, es in seinen gewünschten Typ zu übersetzen?
"Typ-Parameter", die durch eine "gebunden" eingeschränkt werden kann. –