Frage

Ich versuche, einige Scala Code zu schreiben, der so etwas wie tun muss:

class Test[Type] { 
   def main {
       SomeFunc classOf[Type]
       val testVal: Type = new Type()
    }
 }

und es versagt. Verstehe ich natürlich nicht, etwas über Scala allgemeine Parameter. Offensichtlich ist das Missverständnis, dass in C ++, Vorlagen im Wesentlichen wie String-Ersetzungen funktionieren, so neue Art () funktioniert, solange die Klasse übergeben wird, in einen Standard-Konstruktor hat. Doch in Scala, Typen gibt verschiedene Arten von Objekten.

War es hilfreich?

Lösung

Wie Sie weisen darauf hin, C ++ hat Vorlagen. Kurz gesagt, C ++, sagt: „Es ist ein Test für alle Typen T, so dass Test-kompiliert wird.“ Das macht es einfach, Zwänge auf T implizit hinzufügen, aber auf der Seite nach unten, sie sind implizit und können für einen Benutzer Ihrer Klasse schwer zu verstehen, ohne Code zu lesen.

Scala parametrischer Polymorphismus (auch bekannt als Generika) arbeitet viel mehr wie ML, Haskell, Java und C #. In Scala, wenn Sie „class Test [T]“ schreiben Sie sagen, „für alle T gibt es einen Typ-Test [T]“ ohne Einschränkung. Das ist einfacher formal an die Vernunft zu, aber es bedeutet, dass Sie über Einschränkungen zu expliziten haben. Zum Beispiel in Scala kann man sagen, "class Test [T <: Foo]" zu sagen, dass T ein Subtyp von Foo sein muss.

C # hat eine Art und Weise eine Einschränkung zu T in Bezug auf Konstrukteuren hinzufügen, aber leider Scala nicht.

Es gibt ein paar Möglichkeiten, Ihr Problem in der Scala zu lösen. Eine davon ist typsicher, aber ein bt ausführlicher. Der andere ist nicht typsicher.

Die typsichere Art und Weise sieht aus wie

class Test[T](implicit val factory : () => T) {
  val testVal = factory
}

Dann können Sie einen Körper von Fabriken für die Typen haben, die in Ihrem System

object Factories {
  implicit def listfact[X]() = List[X]()
  implicit def setfact[X]() = Set[X]()
  // etc
}

import Factories._
val t = new Test[Set[String]]

Wenn Benutzer Ihrer Bibliothek ihre eigenen Fabriken brauchen, dann können sie ihre eigenen gleichwertigen fügen der Fabriken widersprechen. Ein Vorteil dieser Lösung ist, dass alles, was mit einer Fabrik verwendet werden kann, auch nicht, dass es ein nicht-arg-Konstruktor.

Die nicht-so-typsichere Art und Weise verwendet Reflektion und ein Feature in Scala genannt Manifeste, die eine Art und Weise sind um eine Java-Einschränkung in Bezug auf Typen Löschung zu erhalten

 class Test[T](implicit m : Manifest[T]) {
   val testVal = m.erasure.newInstance().asInstanceOf[T]
 }

Mit dieser Version noch schreiben

class Foo
val t = new Test[Foo]

Allerdings, wenn es keine nicht-arg Konstruktor verfügbar Sie eine Laufzeitausnahme anstelle eines statischen Typs Fehler angezeigt

scala> new Test[Set[String]] 
java.lang.InstantiationException: scala.collection.immutable.Set
at java.lang.Class.newInstance0(Class.java:340)
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top