Comment convertir une variable dans Scala?

199

Étant donné une variable de type Graphics, comment la convertir Graphics2Den Scala?

Eugene Yokota
la source

Réponses:

282

La technique préférée consiste à utiliser la correspondance de motifs. Cela vous permet de gérer avec élégance le cas où la valeur en question n'est pas du type donné:

g match {
  case g2: Graphics2D => g2
  case _ => throw new ClassCastException
}

Ce bloc reproduit la sémantique de la asInstanceOf[Graphics2D]méthode, mais avec une plus grande flexibilité. Par exemple, vous pouvez fournir différentes branches pour différents types, en effectuant efficacement plusieurs conversions conditionnelles en même temps. Enfin, vous n'avez pas vraiment besoin de lever une exception dans la zone fourre-tout, vous pouvez également retourner null(ou de préférence, None), ou vous pouvez entrer une branche de secours qui fonctionne sans Graphics2D.

Bref, c'est vraiment la voie à suivre. C'est un peu plus encombrant syntaxiquement que asInstanceOf, mais la flexibilité supplémentaire en vaut presque toujours la peine.

Daniel Spiewak
la source
19
+1 parce que c'est intéressant, mais un peu trop pour ce scénario. n'est-ce pas?
Eugene Yokota
que se passe-t-il si j'ai déjà une correspondance de motifs mais que j'ai perdu la référence à la valeur castée: <code> base match {case MyConcrete (value) => base.asInstanceOf [MyConcrete] .something (value)} </code>, existe-t-il un moyen d'obtenir ' base 'castée sur MyConcrete même si vous voulez extraire "value" en exploitant l'appel' unapply 'effectué par "case MyConcrete (value)"?
ithkuil
4
Essayez ceci: de base match { case base @ MyConcrete(value) => base.something(value) } toute évidence, l'observation baseest facultative. Vous pouvez tout aussi bien utiliser un nom de variable différent.
Daniel Spiewak
Ce que je n'obtiens pas, c'est comment obtiendriez-vous le résultat de cette correspondance de motifs en une variable? comme en java si c'était String a = (String) b; quel serait l'équivalent scala?
James McMahon
@JamesMcMahonval gResult = g match { case g2: Graphics2D => g2 case _ => throw new ClassCastException }
Kevin Meredith
224
g.asInstanceOf[Graphics2D];
Eugene Yokota
la source
36
Une fois que je me suis habitué à Scala, j'ai appris à ne pas l'utiliser asInstanceOf, car il va à l'encontre du but d'avoir un système de type statique et se sent dégoûtant.
Eugene Yokota
26
Malheureusement, c'est une opération courante lors de l'utilisation de Swing. Pour les opérations de peinture personnalisées, vous devez remplacer la méthode «public void paintComponent (Graphics g)». Le paramètre Graphics est en fait une instance de Graphics2D, mais une conversion est nécessaire. La version de correspondance de motifs est probablement plus verbeuse que garantie. Rappelez-vous: évitez avec séduction l'hypervérosité et la prolixité obscurcissantes!
hohonuuli
7
@hohonuuli Je pense que la distribution est correcte dans ce cas spécifique, mais si vous utilisez des scala-swingcomposants, le paramètre de paintComponent est déjà Graphics2D donc aucune distribution n'est requise
Luigi Plinge
2
Pourquoi c'est si long? Pourquoi "asInstanceOf quand ne peut être que" as "ou" asof "mot-clé ou méthode? Ou pourquoi ils n'ont pas simplement adopté la manière C ++ et Java en option parce que c'est le conventionnel et il n'y a pas de gros problème avec ça?
LEMUEL ADANE
16
@LemuelAdane Le fait que vous utilisiez des transtypages est une odeur de code, cela n'a aucun sens de les rendre plus faciles.
Daenyth