New linearization

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

New linearization

Judson, Ross
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...