Been playing a bit with the new mixin classes; see
http://scala.sygneca.com/code/shared-objects Scala2 forces the first class "extension" to be an "extends" clause, and does not allow "with". This seems a bit draconian -- can an "extends ScalaObject" not be implicitly inserted? The Scala2 change doc tells us that "abstract override", when used in a mixin class that is mixed in with "with", shifts super to be the prior definition within the class being mixed into. In my example I have a "FixedHash" mixin that uses abstract override to redefine how hashes are computed. I also have a "SharedObject" that further refines how equality tests are done. If I want to combine them, the most natural thing to write is (possibly): Mixin class FixedShared extends FixedHash with SharedObject But I can't...because the abstract overrides on FixedHash are no longer used. I could do this: Mixin class FixedShared with FixedHash with SharedObject But that compiler won't accept that. I also cannot write: Mixin class FixedShared extends ScalaObject with FixedHash with SharedObject As the compiler tells me ScalaObject is inherited twice. I can write: Mixin class Fake; Mixin class FixedShared extends Fake with FixedHash with SharedObject; That compiles, but when I do a "with FixedShared", the abstract overrides are lost. I'll have to check to see if the latest compiler exhibits this behavior or not. The linearization definitions in the changes document make sense to me, but it appears that with the way things are currently specified there is no way to combine "with" behaviors and abstract overrides -- each must be specified: Class Var extends Term with FixedHash with SharedObject; Mixin classes currently prohibit constructor values. Observe: /** Log prints a message when hashCode or equals is called. */ mixin class Log { abstract override def hashCode() = { Console.println(tag + ".hashCode"); super.hashCode() } abstract override def equals(o: Any) = { Console.println(tag + ".equals"); super.equals(o); } val tag: String = getClass().getName(); } We've got a log mixin here that logs calls to hashCode and equals. Note the "tag" def -- that's how we're labelling. To use this we do something like this: Class Something with Log { override val tag = "Something"; } I am wondering if it makes sense to allow "val" for mixin parameters. mixin class Log(val tag: String) { abstract override def hashCode() = { Console.println(tag + ".hashCode"); super.hashCode() } abstract override def equals(o: Any) = { Console.println(tag + ".equals"); super.equals(o); } } I can then write: class Something with SharedObject(myFactory) with Log("MyLogger"); Right now constructs must be specified like this: private[shared] def duplicate(f: SharedFactory) = new Var(name) with FixedHash with SharedObject with Log { val factory = f; val tag = "MyLogger"; } Perhaps the compiler can do this transformation automatically... |
Free forum by Nabble | Edit this page |