- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Language improvement proposal - dynamic mixins
Mon, 2011-11-21, 18:59
Hi everyone,
Currently we can mixin traits either when defining a new class or at
object construction. E.g. I like the fact how I can decorate the Map
with MultiMap:
scala> import collection.mutable._
import collection.mutable._
scala> val map = new HashMap[String, Set[String]] with MultiMap[String,
String]
map:
scala.collection.mutable.HashMap[String,scala.collection.mutable.Set[String]]
with scala.collection.mutable.MultiMap[String,String] = Map()
scala> map.addBinding("first", "1a")
res5: map.type = Map(first -> Set(1a))
scala> map.addBinding("first", "1b")
res6: map.type = Map(first -> Set(1b, 1a))
This is really cool. However, when I wanted to use the same construct
with a factory method instead of the constructor, it failed:
scala> HashMap("first" -> Set("1a")) with MultiMap[String, String]
:1: error: ';' expected but 'with' found.
HashMap("first" -> Set("1a")) with MultiMap[String, String]
^
This is pretty sad, because even the core Scala API encourages to use
factory methods in the companion objects and not using the constructor
directly. So I cannot use cool mixins with objects that I cannot control
every detail of construction.
Assume expression evaluates to type A.
What I propose is to add another use case for the "with" keyword with
the following syntax:
expression with T
It should evaluate to an object wrapper of type A with T. The wrapper
would delegate methods defined in type A to the original wrapped object,
but should also support the methods added / overriden by the mixed in
trait(s).
As for the implementation, I feel like it could be implemented using
techniques similar to what JDK dynamic proxies or CGLIB library can do.
The problem with JDK proxies is that they work only with interfaces, not
concrete classes, but CGLIB somehow overcomes this limitation (I don't
know how, but it works - see the net.sf.cglib.proxy.Enhancer class). Of
course, the code for creation of the proxy should be generated by the
compiler whenever it encounters a "expression with trait" construct.
If we had this, it would open many new interesting possibilities, and
for sure make traits more dynamic. You'd be able to add new methods or
roles to existing objects dynamically, which I find very interesting.
What do you think about it? What are the problems that I missed? Or
maybe there is a workaround and I can achieve such dynamic behaviour
right now in Scala 2.9?
Best regards,
Piotr









2011/11/21 Piotr Kołaczkowski <pkolaczk [at] elka [dot] pw [dot] edu [dot] pl>