Actually idea is that I would write some “decorator” in form of trite, and probably use keyword super
instead of some delegate()
method (from base class/trait). Honestly while I was start learning Scala I’ve strong believe that it is possible by the mean of regular traits inheritance … (but when I’ve tried to write that, I understood that it is impossible). When I’ve learned self-types, I’ve got an idea that something similar may help in this problem.
So in general, idea was in somethin like, instead of writing something on top of ForwardingCollection and overriding/decorating some methods of interest, I would probably prefer to write something just on top of
Collection , in form of trait with “super-self-type” like
trait MyCollectionDecorator[T] {
super: java.util.Collection[T] =>
override def add(e: T): Boolean ={
println(s"onAdd: $e")
super.add(e)
}
}
By writing this I would expect that MyCollectionDecorator
almost regular “self-typed” trait, but it would not only require that final implementor mixed it with Collection[T]
, but making some stronger requirement, that implementor should mix it wit some valid implementation of Collection[T]
and that implementing trait/class should stand erectly somewhere “before” MyCollectionDecorator[T]
in linearized inheritance order.
So that it should be valid construct new ForwardingCollection[T] with MyCollectionDecorator[T]
but
writing it in opposite direction - new MyCollectionDecorator[T] with ForwardingCollection[T]
should cause compile time error.
In fact, most “expressive” snippet which I can imagine, may look even like this
trait MyJavaListDecorator[T] {
super: {def get(index: Int): T} =>
override def get(index: Int): T = {
println(s"onGet: $index")
super.get(index)
}
}
And then again, I would expect that new ForwardingList[T] with MyJavaListDecorator[T]
will compiles fine while new MyJavaListDecorator[T] with ForwardingList[T]
reports compilation error.
And also, I should mention, that “partially” this feature is currently working, in particular, with Object.toString
method (in fact, same as with any other Object’s methods)
trait WrapToString {
override def toString: String = "WrapToString: " + super.toString
}
-
this code works correctly even now, but again, it would be nice to “refine” our knowledge about super
in some
indirect way (not only by explicit mentioning that “knowledge” in extends
section)
By the way, current assumption that super
implements all methods of Object
(AnyRef
) in general is false, since it can be violated by overriding toString
with abstract method, so the following code reproduces that scala compiler minor bug
package crafts
object Main {
def main(args: Array[String]): Unit = {
val obj = new Combined
println(s"obj: ${obj}")
}
class Combined extends SuppressToString with WrapToString
abstract class SuppressToString {
override def toString: String
}
trait WrapToString {
override def toString: String = "WrapToString: " + super.toString
}
}
-
while it is quite obvious that SuppressToString
class is abstract, and it’s toString
method is abstract
(and need to be “reimplemented”) compiler does not reject following mixture SuppressToString with WrapToString
and assumes that it is alright with that type. As the result, code compiles but predictably fails on runtime with following error:
Exception in thread "main" java.lang.AbstractMethodError: java.lang.Object.toString()Ljava/lang/String;
at crafts.Main$Combined.crafts$Main$WrapToString$$super$toString(Main.scala:10)
at crafts.Main$WrapToString.toString(Main.scala:17)
at crafts.Main$WrapToString.toString$(Main.scala:17)
at crafts.Main$Combined.toString(Main.scala:10)
at java.lang.String.valueOf(String.java:2994)
at java.lang.StringBuilder.append(StringBuilder.java:131)
at crafts.Main$.main(Main.scala:7)
at crafts.Main.main(Main.scala)
So, from this perspective I may also assume that it can be imaginary semantic extension, that all method from this: Type =>
construction can be automatically visible on super
as well as on this
(if they are missing in types from explicit extends
section), but then compiler should carefully control that all that super
-method usages will be properly validated when making actual mixture of that trite with other trites