<br><font size=2 face="sans-serif"><br>
</font>
<br>
<br><font size=2><tt>Uwe Zdun &lt;uwe.zdun@wu-wien.ac.at&gt; wrote on 08/29/2006
12:20:16 PM:<br>
<br>
&gt; well, why do you think the behavior breaks encapsulation? </tt></font>
<br>
<br><font size=2><tt>When I extend Base with BaseMixin, I'm altering the
interface to Base. &nbsp;I can't safely alter the interface to Derived,
because Base and BaseMixin don't necessarily know about Derived. &nbsp;In
fact, since Derived is completely independent, it might not even exist
when BaseMixin is defined. In gerneral BaseMixin can't be defined to work
correctly with all possible derived classes, that set is open.</tt></font>
<br>
<br><font size=2><tt>I believe when I add a mixin to Base I'm intercepting
Base method invocations. When Derived invokes &quot;next&quot;, it's logically
chaining to Base. The Base may or may not have BaseMixin, but Derived shouldn't
need to know. With BaseMixin intecepting Derived methods, BaseMixin needs
to be made to work with Base &amp; Derived. &nbsp;In practice, this seems
like you can't safely use a mixin on any class thats also used as a superclass
since the mixin will intercept any derived class's interface. &nbsp;</tt></font>
<br>
<br><font size=2><tt>In practice, it's not possible to work with both.
Assume BaseMixin is intercepting a leaf method with a leaf method: if BaseMixin
invokes 'next' it will break Base and if it doesn't invoke 'next' it will
break Derived.</tt></font>
<br>
<br><font size=2><tt>The current behavior means I can't intercept a subset
of the hierarchy, I have to intercept the whole thing. &nbsp;That means
I can't encapsulate the use of a mixin; the mixin gets applied globally.</tt></font>
<br>
<br>
<br><font size=2><tt>&gt; Rather a <br>
&gt; behavior where mixin are not added in precedence before the class
<br>
&gt; hierarchy, requires you to know about the interceptor and might break
<br>
&gt; encapsulation. Consider you are omitting to use &quot;next&quot; in
a method of <br>
&gt; Derived, for instance simply because this method exists nowhere else
in <br>
&gt; the class hierarchy. If the mixin would be introduced after Derived,
you <br>
&gt; would need to modify Derived to introduce a method of the same name
on <br>
&gt; the mixin. If the mixin is always before the class hierarchy, as a
base <br>
&gt; hierarchy developer you don't need to care for how a potential mixin
is <br>
&gt; designed, because you can be sure once a call has reached your class,
<br>
&gt; you can be sure, you cannot accidently introduce side-effects on mixins
<br>
&gt; (maybe designed later by other developers).<br>
</tt></font>
<br><font size=2><tt>To be clear, I agree that a mixin should take precedence
over the class it's mixed into. &nbsp;I don't think it should take precedence
over classes derived from the class it's mixed into. &nbsp;If I wanted
to intercept method invocations on Derived, I would add a mixin to Derived
but my explicit semantic is that I want to intercept methods on Base.</tt></font>
<br>
<br>
<br>
<br><font size=2><tt>To ground this discussion a bit more in reality, my
base class accesses hardware (Device). &nbsp;I then have a AppDevice class
derived from the Device class that I use in my application. &nbsp;AppDevice
will get a method, perform some processing and then invoke Device (via
'next'). </tt></font>
<br>
<br><font size=2><tt>So from the app point of view I have: </tt></font>
<br><font size=2><tt>AppDevice --&gt; Device</tt></font>
<br>
<br><font size=2><tt>For testing purposes I want to use a simulator. I
created a DeviceSim class that reads and writes a buffer instead of the
HW. I don't want my derived classes to know or care if it's using the simulator
or the actual device. &nbsp;In either case the classes define leaf methods;
the methods don't (and can't) chain.</tt></font>
<br>
<br><font size=2><tt>In the test environment I want DeviceSim to intercept
Device methods (&quot;Device mixin add DeviceSim&quot;): </tt></font>
<br><font size=2><tt>AppDevice --&gt; DeviceSim --&gt; Device &nbsp;</tt></font>
<br>
<br><font size=2><tt>But what I get is: &nbsp;</tt></font>
<br><font size=2><tt>DeviceSim --&gt; AppDevice --&gt; Device</tt></font>
<br>
<br><font size=2><tt>Since both Device and DeviceSim have leaf methods,
adding DeviceSim as mixin to Device breaks AppDevice. &nbsp;It's the documented
behavior, but it doesn't feel like the right behavior. &nbsp;The behavior
I wanted (and what my code expressed) was to intercept Device methods not
AppDevice methods. &nbsp;I don't see any way to limit interception to the
subset of the hierarchy that I want.</tt></font>
<br>
<br><font size=2><tt>Is what I'm trying to do unreasonable? It feels like
I'm using the language features as intended, I just don't get the desired
result. &nbsp;</tt></font>
<br>
<br>