web-dev-qa-db-fra.com

Scala Motif correspondant à la confusion avec option [tout]

J'ai le suivant Scala code.

import scala.actors.Actor

object Alice extends Actor {
  this.start
  def act{
    loop{
      react {
        case "Hello" => sender ! "Hi"
        case i:Int => sender ! 0
      }
    }
  }
}
object Test {
  def test = {
    (Alice !? (100, "Hello")) match {
      case i:Some[Int] => println ("Int received "+i)
      case s:Some[String] => println ("String received "+s)
      case _ =>
    }
    (Alice !? (100, 1)) match {
      case i:Some[Int] => println ("Int received "+i)
      case s:Some[String] => println ("String received "+s)
      case _ =>
    }
  }
}

Après avoir fait Test.test, Je reçois la sortie:

scala> Test.test
Int received Some(Hi)
Int received Some(0)

Je m'attendais à la sortie

String received Some(Hi)
Int received Some(0)

Quelle est l'explication?

En deuxième question, je reçois unchecked avertissements avec ce qui précède comme suit:

C:\scalac -unchecked a.scala
a.scala:17: warning: non variable type-argument Int in type pattern Some[Int] is unchecked since it is eliminated by erasure
      case i:Some[Int] => println ("Int received "+i)
             ^
a.scala:18: warning: non variable type-argument String in type pattern Some[String] is unchecked since it is eliminated by erasure
      case s:Some[String] => println ("String received "+s)
             ^
a.scala:22: warning: non variable type-argument Int in type pattern Some[Int] is unchecked since it is eliminated by erasure
      case i:Some[Int] => println ("Int received "+i)
             ^
a.scala:23: warning: non variable type-argument String in type pattern Some[String] is unchecked since it is eliminated by erasure
      case s:Some[String] => println ("String received "+s)
             ^
four warnings found

Comment puis-je éviter les avertissements?

EDIT: Merci pour les suggestions. L'idée de Daniel est belle mais ne semble pas fonctionner avec des types génériques, comme dans l'exemple ci-dessous

def test[T] = (Alice !? (100, "Hello")) match { 
   case Some(i: Int) => println ("Int received "+i) 
   case Some(t: T) => println ("T received ") 
   case _ =>  
}

Ce qui suit erreur L'avertissement est rencontré: warning: abstract type T in type pattern T is unchecked since it is eliminated by erasure

34
Jus12

Cela est dû à l'effacement de type. Le JVM ne connaît pas de paramètre de type, sauf sur les tableaux. À cause de cela, Scala code ne peut pas vérifier si un Option est un Option[Int] ou un Option[String] - Cette information a été effacée.

Vous pourriez corriger votre code de cette façon, cependant:

object Test {
  def test = {
    (Alice !? (100, "Hello")) match {
      case Some(i: Int) => println ("Int received "+i)
      case Some(s: String) => println ("String received "+s)
      case _ =>
    }
    (Alice !? (100, 1)) match {
      case Some(i: Int) => println ("Int received "+i)
      case Some(s: String) => println ("String received "+s)
      case _ =>
    }
  }
}

De cette façon, vous ne testez pas ce que le type de Option est, mais que le type de son contenu suppose - en supposant qu'il y a du contenu. A None tombera à travers le cas par défaut.

48
Daniel C. Sobral

Toute information sur les paramètres de type n'est disponible que lors de la compilation, pas au moment de l'exécution (celle-ci est appelée effacement de type). Cela signifie qu'à l'exécution, il n'y a pas de différence entre Option[String] et Option[Int], donc tout motif correspondant sur le type Option[String], va également correspondre Option[Int] Parce qu'à l'exécution des deux est juste Option.

Comme ce n'est presque toujours pas ce que vous avez l'intention, vous obtenez un avertissement. Le seul moyen d'éviter l'avertissement n'est pas de vérifier le type générique de quelque chose à l'exécution (qui va bien parce que cela ne fonctionne pas comme si vous le souhaitez de toute façon).

Il n'y a aucun moyen de vérifier si un Option est un Option[Int] ou un Option[String] au moment de l'exécution (autre que d'inspecter le contenu s'il s'agit d'un Some).

8
sepp2k