A most compelling example!
So, I think you can see what is happening here. quick_glance makes a call to a
method that will only be defined in a subclass. tall_glass works, because when
it is mixed in (when the concrete interstitial class is built),
glanceAtVermouth is defined in a superclass.
To put the problem in terms of your example, the compiler is asking: Are you
sure that every time your gazes passes over the vermouth you want to sip and
contemplate? And if you do, what exactly is it that you plan to sip and
contemplate?
One solution is to recast your example to be more modular. Neither the gin nor
the vermouth should presuppose that their only purpose is to participate in the
making of martinis. It is really the martini that knows the recipe involves
three steps, pouring gin, glancing at vermouth, and finally sipping and
contemplating.
Alternatively, if your actual application has such dependencies, if the mixins
_do_ presuppose their purpose, you need a way to communicate that to the
compiler. There are two theories on this: required methods and interfaces.
In Lisp-like languages, the answer would be that your vermouth mixin would have
to say something like:
<method name="sip_and_contemplate" required="true" />
[We have this for attributes already, but not for methods. We should extend it
to methods.]
In Java-like languages, the answer would be that you would define a
martini-making interface and that your mixin would require that interface.
I lean toward the required method approach myself, because I think it is more
flexible and more in keeping with the OpenLaszlo spirit.
On 2009-12-04, at 09:46, Rami Ojares / AMG Oy wrote:
>> I'd be interested to know more about the specific issue the swf10
>> compiler was having a problem with. The LZX compiler is supposed to
>> 'do the right thing' for you. It does not actually write the mixin
>> out as a class -- it just uses it as a template to write the flattened
>> class chain that your mixins specify. So, I think there is either a
>> bug in the compiler, or a bug in your modularization.
>
> The following code is created to demonstrate how swf10 compiler treats
> mixins. You can then decide whether you think
> this is appropriate or not.
>
> This example WORKS in swf8.
> Compiling to swf10 the following error is produced:
>
> Stray error string from external compiler:
> /opt/prg/tomcat/apache-tomcat-6.0.18/temp/lzswf9/opt/prg/tomcat/apache-tomcat-6.0.18/webapps/exodus/test/build/churchill_dry_martini/$lzc$class_quick_glance_at_a_bottle_of_vermouth$view.as(9):
> sar.: 1 Virhe: Call to a possibly undefined method sip_and_contemplate
>
> ("Virhe" means "error" in english)
>
> File churchill_dry_martini.lzx
> -------------------------------
> <canvas debug="true">
>
> <include href="tall_glass_of_gin.lzx"/>
> <include href="quick_glance_at_a_bottle_of_vermouth.lzx"/>
>
> <class name="churchill_dry_martini" with="tall_glass_of_gin,
> quick_glance_at_a_bottle_of_vermouth">
> <method name="sip_and_contemplate">
> Debug.write("I do not understand this squeamishness about the use
> of gas. \
> We have definitely adopted the position at the Peace
> Conference of \
> arguing in favour of the retention of gas as a permanent
> method of warfare. \
> It is sheer affectation to lacerate a man with the poisonous
> fragment of a \
> bursting shell and to boggle at making his eyes water by means
> of lachrymatory gas. \
> I am strongly in favour of using poisoned gas against
> uncivilised tribes. \
> The moral effect should be so good that the loss of life
> should be reduced to a minimum. \
> It is not necessary to use only the most deadly gasses: gasses
> can be used which\
> cause great inconvenience and would spread a lively terror and
> yet would leave no \
> serious permanent effects on most of those affected.");
> </method>
> </class>
>
> <churchill_dry_martini>
> <handler name="oninit">
> pourGin();
> </handler>
> </churchill_dry_martini>
> </canvas>
>
> File tall_glass_of_gin.lzx
> -------------------------------
> <library>
> <mixin name="tall_glass_of_gin">
> <method name="pourGin">
> Debug.write("Take a long glass");
> Debug.write("Pour it full of Bombay Sapphire");
> glanceAtVermouth();
> </method>
> </mixin>
> </library>
>
> File quick_glance_at_a_bottle_of_vermouth.lzx
> ---------------------------------------------
> <library>
> <mixin name="quick_glance_at_a_bottle_of_vermouth">
> <method name="glanceAtVermouth">
> Debug.write("Just a quick glance. It's enough.");
> sip_and_contemplate();
> </method>
> </mixin>
> </library>
>
>