72 votes

Scala double définition (2 méthodes ont le même type gomme)

J'ai écrit ça en scala et ça ne compilera pas:

 class TestDoubleDef{
  def foo(p:List[String]) = {}
  def foo(p:List[Int]) = {}
}
 

le compilateur notifie:

 [error] double definition:
[error] method foo:(List[String])Unit and
[error] method foo:(List[Int])Unit at line 120
[error] have same type after erasure: (List)Unit
 

Je sais que JVM n’a pas de support natif pour les génériques, je comprends donc cette erreur.

Je pourrais écrire des wrappers pour List [String] et List [Int] mais je suis paresseux :)

Je doute, mais existe-t-il un autre moyen d'exprimer List [String] n'est pas du même type que List [Int]?

Merci.

56voto

Landei Points 30509

J'aime Michael Krämer l'idée d'utiliser implicites, mais je pense qu'il peut être appliqué plus directement:

case class IntList(list: List[Int])
case class StringList(list: List[String])

implicit def il(list: List[Int]) = IntList(list)
implicit def sl(list: List[String]) = StringList(list)

def foo(i: IntList) { println("Int: " + i.list)}
def foo(s: StringList) { println("String: " + s.list)}

Je pense que c'est tout à fait lisible et simple.

[Mise à jour]

Il y a un autre moyen facile qui semble fonctionner:

def foo(p: List[String]) { println("Strings") }
def foo[X: ClassManifest](p: List[Int]) { println("Ints") }
def foo[X: ClassManifest, Y: ClassManifest](p: List[Double]) { println("Doubles") }

Pour chaque version que vous avez besoin d'un autre type de paramètre, donc ce n'est pas à l'échelle, mais je pense que pour trois ou quatre versions, c'est bien.

[Mise à jour 2]

Pour les deux méthodes, j'ai trouvé un autre truc sympa:

def foo(list: => List[Int]) = { println("Int-List " + list)}
def foo(list: List[String]) = { println("String-List " + list)}

55voto

Jean-Philippe Pellet Points 25240

Au lieu d'inventer des valeurs implicites factices, vous pouvez utiliser le DummyImplicit défini dans Predef qui semble être fait exactement pour cela:

 class TestMultipleDef {
  def foo(p:List[String]) = ()
  def foo(p:List[Int])(implicit d: DummyImplicit) = ()
  def foo(p:List[java.util.Date])(implicit d1: DummyImplicit, d2: DummyImplicit) = ()
}
 

13voto

Aaron Novstrup Points 10742

Pour comprendre Michael Krämer la solution, il est nécessaire de reconnaître que les types des paramètres implicites sont sans importance. Ce qui est important, c'est que leurs types sont distincts. Le code suivant fonctionne de la même manière:

class TestDoubleDef {
   object dummy1 { implicit val dummy: dummy1.type = this }
   object dummy2 { implicit val dummy: dummy2.type = this }

   def foo(p:List[String])(implicit d: dummy1.type) = {}
   def foo(p:List[Int])(implicit d: dummy2.type) = {}
}

object App extends Application {
   val a = new TestDoubleDef()
   a.foo(1::2::Nil)
   a.foo("a"::"b"::Nil)
}

Bien qu'il soit plus détaillé, cette approche soulage l'appelant de la charge de la fourniture de l'implicite arguments. En fait, cela fonctionne même si le dummyN objets sont privés de l' TestDoubleDef classe.

12voto

Viktor Klang Points 14826

En raison des merveilles de l'effacement de type, les paramètres de type de la liste de vos méthodes sont effacés lors de la compilation, réduisant ainsi les deux méthodes à la même signature, ce qui est une erreur du compilateur.

9voto

Michel Krämer Points 2518

Comme le dit déjà Viktor Klang, le type générique sera effacé par le compilateur. Heureusement, il existe une solution de contournement:

 class TestDoubleDef{
  def foo(p:List[String])(implicit ignore: String) = {}
  def foo(p:List[Int])(implicit ignore: Int) = {}
}

object App extends Application {
  implicit val x = 0
  implicit val y = ""

  val a = new A()
  a.foo(1::2::Nil)
  a.foo("a"::"b"::Nil)
}
 

Merci pour Michid pour le tuyau!

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