If you are just trying to get your class to follow two separate incompatible interfaces, you will have to write wrappers instead. For instance,
implicit case class ImplAsFoo(impl: Impl) extends Foo { def asFoo = this def doSomething: Int = 5 }
Now you can
impl.asFoo
on the downloader to go to the Foo wrapper.
In some cases, however, a type type template can be used more naturally to provide connectivity functionality:
trait IFoo[A] { def doSomething: Int } trait IBar[A] { def doSomething: String } // These need to be companions so :paste if you're using REPL class Impl { def doSomething { println("Hey!") } } object Impl { implicit object FooImpl extends IFoo[Impl] { def doSomething = 5 } implicit object BarImpl extends IBar[Impl] { def doSomething = "salmon" } } def needsFoo[A <: Impl: IFoo](a: A) = implicitly[IFoo[Impl]].doSomething scala> needsFoo(new Impl) res1: Int = 5 scala> (new Impl).doSomething Hey!
This is not exactly the same, but it also fixes the problem of having different implementations without turning off naming schemes. (If you need to doSomething with an doSomething object, you must pass it as a parameter to an implicit object that handles this case.)
If you already have traits, then, of course, this will not help you. But when you develop from scratch, instead of having a bunch of features with incompatible methods, you can try class types.
Finally, if you canβt help when a bunch of untyped things mix together, of which you need to choose Foo s, you need to come up with more complex schemes:
trait CanBeFoo { def asFoo: Foo } trait Foo { def doSomething: Int } // :paste these two together class Impl extends CanBeFoo { def doSomething { println("Ho!") } def asFoo = ImplAsFoo(this) } case class ImplAsFoo(impl: Impl) extends Foo { def doSomething = 6 } val myList = List("salmon", new Impl, new Foo { def doSomething = 4 }) def doIt(f: Foo) { println(f.doSomething) } myList.foreach { case f: Foo => doIt(f) case cf: CanBeFoo => doIt(cf.asFoo) case _ => println("nuh-uh") } // Produces // nuh-uh // 6 // 4
You may prefer an intermediate map:
myList.map{ case cf: CanBeFoo => cf.asFoo; case x => x }.foreach{ case f: Foo => println(f.doSomething) case _ => println("nuh-uh") }