I'm implementing a very simple builder pattern for a map-like container:
trait KeyValueContainer[K,V] {
private var props: Map[K, V] = new HashMap[K, V]
private var built = false
/**
* Adds a key/value pair
*/
def +=(key: K, value: V): KeyValueContainer[K,V] = {
if (built)
throw new BuilderException
props = props + (key -> value)
this
}
def build = {
built = true
this
}
}
class MyContainer extends KeyValueContainer[String, Double]
When using the above "+=" or "build" methods on a "new MyContainer()", the result is of type KeyValueContainer[String,Double] in both occassions...
I'm pretty sure I read somewhere in the past that this could be somehow made to return the actual MyContainer sub-type instead. Would you use method return type covariance for this (Java-style), or is there a more type-safe / better solution to this in your view?
Thanks!
And here it is:
http://docs.scala-lang.org/overviews/core/architecture-of-scala-collections.html
The pattern relies on how implicits are resolved at compile-time. Basically, if there are multiple implicits in scope, the compiler picks the most specific one (in your case, the subtype builder you need).
In this way, you can do generic implementations in a base-class and get subclass builders through an implicit argument.
Here is an example of what I did for one of my own projects:
https://gist.github.com/hejfelix/8a0270855d498d7981f9
Another important aspect of this pattern is explicit self-typing: http://www.scala-lang.org/node/124
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With