一种只应接受Scala中A或B或C实例的方法

时间:2016-01-24 23:07:49

标签: scala types

我会确保方法只接受ABC的实例。我不想修改ABC的代码。

case class A
case class B
case class C
def method(aOrbOrc: Any) = ???

// method("toto") should not compile

2 个答案:

答案 0 :(得分:4)

你可以使用Miles Sabin的想法来实现联合类型(下面的代码取自Rex Kerr的variant):

trait Contra[-A] {}
type Union[A,B,C] = {
  type Check[Z] = Contra[Contra[Z]] <:< Contra[Contra[A] with Contra[B] with Contra[C]]
}

然后做:

def method[T: Union[A,B,C]#Check](t: T) = ???

例如:

def method[T: Union[Int,String,Boolean]#Check](t:T) = ???

method(1)     // OK
method("foo") // OK
method(true)  // OK
method(1.5)   // does not compile

详细了解herehere是指向Miles帖子的链接。

答案 1 :(得分:4)

您可以使用Type Class。

case class A(s: String)
case class B(i: Int)
case class C(i1: Int, i2: Int)

// Type Class
trait ABC[T] { 
    def bar(t: T): String
}
// Instances
implicit object ABC_A extends ABC[A] {
    override def bar(t: A): String = "A : s = " + t.s
}
implicit object ABC_B extends ABC[B] {
    override def bar(t: B): String = "B : i = " + t.i
}
implicit object ABC_C extends ABC[C] {
    override def bar(t: C): String = "C : i1 = " + t.i1 + ", i2 = " + t.i2
}

def method[T](abc: T)(implicit instance: ABC[T]) = println(instance.bar(abc))

method(A("AAAAA")) // => A : s = AAAAA
method(B(123))     // => B : i = 123
method(C(9, 5))    // => C : i1 = 9, i2 = 5
method(1)          // compilation error