Comment puis-je configurer multiples bornes de type ORED à Scala
-
05-10-2019 - |
Question
Est-il possible de faire quelque chose comme ça dans Scala :
class MyTest {
def foo[A <: String _or_ A <: Int](p:List[A]) = {}
}
C'est, le type A
pourrait être un String
ou Int
. Est-ce possible?
La solution
Pas vraiment possible comme vous le dites, mais vous pouvez le faire en utilisant le modèle de classe de type. Par exemple, de :
sealed abstract class Acceptable[T]
object Acceptable {
implicit object IntOk extends Acceptable[Int]
implicit object LongOk extends Acceptable[Long]
}
def f[T: Acceptable](t: T) = t
scala> f(1)
res0: Int = 1
scala> f(1L)
res1: Long = 1
scala> f(1.0)
<console>:8: error: could not find implicit value for parameter ev: Acceptable[Double]
f(1.0)
^
EDIT
Cela fonctionne si classe et objets sont des compagnons. Sur REPL, si vous tapez chacun sur une ligne différente (par exemple un « résultat » apparaît entre eux), ils ne sont pas des compagnons. Vous pouvez taper comme ci-dessous, bien que:
scala> sealed abstract class Acceptable[T]; object Acceptable {
| implicit object IntOk extends Acceptable[Int]
| implicit object LongOk extends Acceptable[Long]
| }
defined class Acceptable
defined module Acceptable
Autres conseils
Vous pourriez obtenir un peu de kilométrage du type ou l'autre. Cependant, la hiérarchie est soit scellée et traiter plus de deux types devient lourd.
scala> implicit def string2either(s: String) = Left(s)
string2either: (s: String)Left[String,Nothing]
scala> implicit def int2either(i: Int) = Right(i)
int2either: (i: Int)Right[Nothing,Int]
scala> type SorI = Either[String, Int]
defined type alias SorI
scala> def foo(a: SorI) {a match {
| case Left(v) => println("Got a "+v)
| case Right(v) => println("Got a "+v)
| }
| }
foo: (a: SorI)Unit
scala> def bar(a: List[SorI]) {
| a foreach foo
| }
bar: (a: List[SorI])Unit
scala>
scala> foo("Hello")
Got a Hello
scala> foo(10)
Got a 10
scala> bar(List(99, "beer"))
Got a 99
Got a beer
Une autre solution est wrapper cours:
case class IntList(l:List[Int])
case class StringList(l:List[String])
implicit def li2il(l:List[Int]) = IntList(l)
implicit def ls2sl(l:List[String]) = StringList(l)
def foo(list:IntList) = { println("Int-List " + list.l)}
def foo(list:StringList) = { println("String-List " + list.l)}
Il y a ce hack:
implicit val x: Int = 0
def foo(a: List[Int])(implicit ignore: Int) { }
implicit val y = ""
def foo(a: List[String])(implicit ignore: String) { }
foo(1::2::Nil)
foo("a"::"b"::Nil)
Et aussi cette question .