387 votes

Comment puis-je contourner l'effacement de type sur Scala? Ou, pourquoi ne puis-je pas obtenir le paramètre type de mes collections?

C’est une triste réalité sur la Scala que si vous instanciez une liste [Int], vous pouvez vérifier que votre instance d’est une liste, et vous pouvez vérifier que n’importe quel élément individuel de celui-ci est un Int, mais pas qu’il y a une liste [entier], comme on peut facilement vérifier :

-Option décochée met le blâme carrément sur l’effacement du type :

Pourquoi est-ce et comment les obtenir autour de lui ?

243voto

Daniel C. Sobral Points 159554

Cette réponse utilise l' Manifest-API, qui est obsolète depuis la Scala 2.10. Veuillez voir les réponses ci-dessous pour plus de solutions actuelles.

Scala a été définie avec le Type d'Effacement, parce que la Machine Virtuelle Java (JVM), contrairement à Java, n'a pas de génériques. Cela signifie que, au moment de l'exécution, seule la classe existe, non pas de ses paramètres de type. Dans l'exemple, la JVM sait que c'est de la manipulation d'un scala.collection.immutable.List, mais pas que cette liste est paramétrable avec des Int.

Heureusement, il y a une option dans Scala qui vous permet de contourner cela. C'est le Manifeste. Un Manifeste est de classe dont les instances sont des objets représentant des types. Depuis ces instances sont des objets, vous pouvez les transmettre autour de, de les stocker, et plus généralement à l'appel de méthodes sur eux. Avec le soutien de paramètres implicites, il devient un outil très puissant. Prenez l'exemple suivant, par exemple:

object Registry {
  import scala.reflect.Manifest

  private var map= Map.empty[Any,(Manifest[_], Any)] 

  def register[T](name: Any, item: T)(implicit m: Manifest[T]) {
    map = map.updated(name, m -> item)
  }

  def get[T](key:Any)(implicit m : Manifest[T]): Option[T] = {
    map get key flatMap {
      case (om, s) => if (om <:< m) Some(s.asInstanceOf[T]) else None
    }     
  }
}

scala> Registry.register("a", List(1,2,3))

scala> Registry.get[List[Int]]("a")
res6: Option[List[Int]] = Some(List(1, 2, 3))

scala> Registry.get[List[String]]("a")
res7: Option[List[String]] = None

Lors du stockage d'un élément, nous conservons un "Manifeste" de trop. Un Manifeste est une classe dont les instances représentent Scala types. Ces objets ont plus d'information que la JVM ne, ce qui nous permet de tester l'intégralité paramétrée type.

Notez, cependant, que l' Manifest est encore une évolution de la fonction. Comme un exemple de ses limites, en ce moment, ne sait rien au sujet de la variance, et n'assume tout est co-variante. J'attends qu'il va obtenir plus stable et solide, et une fois à la Scala de réflexion de la bibliothèque, actuellement en cours de développement, est parachevé.

103voto

tksfz Points 481

Vous pouvez le faire à l’aide de TypeTags ou ClassTags (comme Daniel déjà mentionne, mais je vais juste préciser il explicitement) :

Scala intègre le ClassTag dans la correspondance de modèle automatiquement et ne sera pas imprimé des avertissements.

64voto

Miles Sabin Points 13604

Vous pouvez utiliser le `` type classe de informes pour obtenir le résultat que vous recherchez,

Session d’échantillon REPL,

La opération sera aussi précise wrt effacement que possible compte tenu de la portée des instances disponibles.

17voto

thricejamie Points 59

Je suis venu avec une solution relativement simple qui serait suffisant en cas d’utilisation limitée, essentiellement d’emballage des types paramétrés qui souffriraient le problème d’effacement de type dans les classes wrapper qui peut être utilisé dans une instruction de match.

Cela a les résultats escomptés et limite le contenu de notre classe affaire au type désiré, listes de chaîne.

Plus de détails ici : http://www.scalafied.com/?p=60

13voto

axaluss Points 975

Il y a un moyen de surmonter le type d'effacement question en Scala. En Surmontant Type d'Effacement dans la correspondance de 1 et de Surmonter Type d'Effacement dans la Correspondance de 2 (Variance) sont une explication de comment le code de certaines aides à envelopper les types, y compris la Variance, pour la correspondance.

J'espère que cela a aidé.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X