Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I delegate to a member in Scala?

Tags:

proxy

scala

Is it possible in Scala to write something like:

trait Road {
  ...
}

class BridgeCauseway extends Road {
  // implements method in Road
}

class Bridge extends Road {
  val roadway = new BridgeCauseway()

  // delegate all Bridge methods to the `roadway` member
}

or do I need to implement each of Road's methods, one by one, and call the corresponding method on roadway?

like image 225
Bill Avatar asked Mar 29 '11 18:03

Bill


2 Answers

The easiest way to accomplish this is with an implicit conversion instead of a class extension:

class Bridge { ... }
implicit def bridge2road(b: Bridge) = b.roadway

as long as you don't need the original Bridge to be carried along for the ride (e.g. you're going to store Bridge in a collection of Road).

If you do need to get the Bridge back again, you can add an owner method in Road which returns an Any, set it using a constructor parameter for BridgeCauseway, and then pattern-match to get your bridge:

trait Road {
  def owner: Any
  ...
}

class BridgeCauseway(val owner: Bridge) extends Road { . . . }

class Bridge extends Road {
  val roadway = new BridgeCauseway(this)
  ...
}

myBridgeCauseway.owner match {
  case b: Bridge => // Do bridge-specific stuff
  ...
}
like image 138
Rex Kerr Avatar answered Nov 08 '22 09:11

Rex Kerr


If you can make Bridge a trait you'll be sorted.

scala> trait A {
     |   val x: String
     | }
defined trait A

scala> class B extends A {
     |   val x = "foo"
     |   val y = "bar"
     | }
defined class B

scala> trait C extends A { self: B =>         
     |   val z = "baz"               
     | }
defined trait C

scala> new B with C
res51: B with C = $anon$1@1b4e829

scala> res51.x
res52: java.lang.String = foo

scala> res51.y
res53: java.lang.String = bar

scala> res51.z
res54: java.lang.String = baz
like image 21
Synesso Avatar answered Nov 08 '22 09:11

Synesso