I would ensure that a method should only accept instances of A or B or C. And I don't want to modify the code of A, B and C.
case class A
case class B
case class C
def method(aOrbOrc: Any) = ???
// method("toto") should not compile
I would ensure that a method should only accept instances of A or B or C. And I don't want to modify the code of A, B and C.
case class A
case class B
case class C
def method(aOrbOrc: Any) = ???
// method("toto") should not compile
 
    
     
    
    You could use Miles Sabin's idea for implementing union types (code below is taken from Rex Kerr's variant):
trait Contra[-A] {}
type Union[A,B,C] = {
  type Check[Z] = Contra[Contra[Z]] <:< Contra[Contra[A] with Contra[B] with Contra[C]]
}
then do:
def method[T: Union[A,B,C]#Check](t: T) = ???
for example:
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
You can use 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
