简体   繁体   中英

Scala bound on part of a type parameter

I have a class that takes a type parameter and I'd like a method on the class to be restricted to arguments that adhere to that parameterization. However when the class is concretely instantiated the type parameter has additional traits mixed in that I'd like to ignore for the method. Concretely:

trait X {def str = "X"}
trait X1 extends X {def str = "X1"}
trait X2 extends X {def str = "X1"}

trait Y

class Foo[A <: X] { def do(a:A) = a.str}

val f = new Foo[X1 with Y]
val x1 = new X1 {}
val x2 = new X2 {}
val y = new Y {}

// I want this to compile
f.do(x1)
// and these to not compile
f.do(x2)
f.do(y)

Currently none of the three final statements compile, but I'd like to set the type parameter on the Foo.do method such that only the first statement compiles. I don't know how to 'extract' the appropriate part of the type of A from the declaration however.

I've hit upon a solution, though it is not too elegant and I'm open to other ones. Since, by supposition, I am only going to use methods on X in my do method (as they are the only ones visible to the type) I can cast the input argument to the appropriate type using an implicit as follows:

trait X {def str = "X"}
trait X1 extends X {override def str = "X1"}
trait X2 extends X {override def str = "X1"}

trait Y

trait X {def str = "X"}

implicit def x2xWy[Xt <: X](x:Xt):Xt with Y = x.asInstanceOf[Xt with Y]

class Foo[A <: X] { def doIt[A1](a:A1)(implicit toA:(A1 => A)) = toA(a).str}

// this compiles
f.doIt(x1)
// and these do not
f.doIt(x2)
f.doIt(y)

That said, this approach is still suboptimal in several ways, namely we need to know at compile time all of the types that might be mixed in to A at runtime. Also the scope of the implicit needs to be carefully managed to ensure that it does not leak out into a situation where it could cause problems.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM