57 votes

Quelles sont les différences entre asInstanceOf [T] et (o: T) dans Scala?

J'ai vu qu'il y a deux méthodes pour lancer un objet dans Scala:

 foo.asInstanceOf[Bar]
(foo: Bar)
 

Lorsque j'ai essayé, j'ai constaté que asInstanceOf n'utilisait pas la conversion implicite, contrairement à l'autre.

Quelles sont les différences de comportement entre ces deux méthodes? Et où est-il recommandé d'utiliser l'un sur l'autre?

100voto

pelotom Points 14817
  • foo.asInstanceOf[Bar] est un type de fonte, qui est principalement à l'exécution de l'opération. Il est dit que le compilateur doit être contraint de croire qu' foo est Bar. Cela peut entraîner une erreur (un ClassCastException) si, et quand, foo est évaluée à être autre chose qu'un Bar lors de l'exécution.

  • foo:Bar est un type de nom, qui est entièrement au moment de la compilation de l'opération. C'est en donnant le compilateur d'aide pour comprendre le sens de votre code, sans forcer à croire tout ce qui pourrait éventuellement être faux; pas de runtime échecs peuvent résulter de l'utilisation de type ascriptions.

Type ascriptions peut également être utilisé pour déclencher des conversions implicites. Par exemple, vous pouvez définir la suite de la conversion implicite:

implicit def foo(s:String):Int = s.length

et de s'assurer de son utilisation comme suit:

scala> "hi":Int                                 
res29: Int = 2

Attribuer un type Int d'un String seraient normalement au moment de la compilation type d'erreur, mais avant d'abandonner le compilateur recherche les conversions implicites pour le problème. Le particulier de la conversion implicite qui sera utilisé dans un contexte donné est connu au moment de la compilation.

Inutile de dire, les erreurs d'exécution sont indésirables, ainsi que la mesure dans laquelle vous pouvez spécifier les choses dans un type-safe manière (sans l'aide d' asInstanceof), le mieux! Si vous vous trouvez à l'aide de asInstanceOf, vous devriez probablement utiliser des match à la place.

18voto

Sandor Murakozi Points 2549

Pelotom réponse du couvre la théorie assez sympa, voici quelques exemples pour le rendre plus clair:

def foo(x: Any) {
  println("any")
}

def foo(x: String) {
  println("string")
}


def main(args: Array[String]) {
  val a: Any = new Object
  val s = "string"

  foo(a)                       // any
  foo(s)                       // string
  foo(s: Any)                  // any
  foo(a.asInstanceOf[String])  // compiles, but ClassCastException during runtime
  foo(a: String)               // does not compile, type mismatch
}

Comme vous pouvez le voir le type de nom peut être utilisé pour résoudre disambiguations. Parfois, ils peuvent être encore sans réponse par le compilateur (voir plus loin), ce qui signale une erreur et vous devez le résoudre. Dans d'autres cas (comme dans l'exemple), il utilise juste la "mauvaise" la méthode, pas ce que vous voulez. foo(a: String) ne compile pas, montrant que le type d'attribution n'est pas un casting. Comparer avec la ligne précédente, où le compilateur est heureux, mais vous obtenez une exception, si l'erreur est détectée, alors le type d'attribution.

Vous recevrez un insolubles ambiguïté si vous aussi ajouter une méthode

def foo(xs: Any*) {
  println("vararg")
}

Dans ce cas, la première et la troisième invocation de foo pas compiler, le compilateur ne peut pas décider si vous voulez l'appeler foo avec un seul Tout param, ou avec les varargs, comme les deux d'entre eux semble être tout aussi bon => vous devez utiliser un type d'attribution à l'aide du compilateur.

Modifier voir aussi Quel est le but de type nom de Scala?

10voto

Jon McAuliffe Points 1906

"Programming in Scala" couvre cette dans un peu de détail dans le Chapitre 15 - Cas des Classes et le Pattern Matching.

Au fond, le deuxième formulaire peut être utilisé comme "Tapé Pattern" dans un modèle de match, donnant l'isInstanceOf et asInstanceOf fonctionnalité. Comparer

if (x.isInstanceOf[String]) {
val s = x.asInstanceOf[String]
s.length
} else ...

vs

def checkFoo(x: Any) = x match {
  case s: String => s.length
  case m: Int => m
  case _ => 0
}

Les auteurs de l'indice que le niveau de verbosité de la isInstance* façon de faire les choses est volontaire pour vous motiver dans la correspondance de motif de style.

Je ne sais pas quel modèle est plus efficace pour un simple catalogué sans un test si.

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