What are Mixins?
As we saw in the previous sections, classes which you write in APLX can inherit from other classes; this means that the methods and properties of the parent class (or classes) are available in the child class.
Although the concept of inheritance is very powerful, there are some circumstances where more flexibility is required. In APLX, a class cannot inherit from multiple different classes, only from one parent class (although that might itself inherit from its parent, and so on). Nor can a class inherit from an external class; for example, you cannot write an APL class which directly inherits from a Java class.
'Mixins' address both of these requirements. They allow you to extend your user-defined classes so that, at run-time, they dynamically 'mix in' functionality (i.e. methods and properties, and perhaps events) from one or more other classes; these can be internal (user-defined, and written in APL), or external (.Net, Java, Ruby etc, or a built-in APLX system class).
Because mixins are attached dynamically at runtime, they are very flexible. For example, in a commercial application you might have an Invoice class (which perhaps inherits from an AccountingDocument class). If you wanted to add functionality which would allow the Invoice class to be faxed or e-mailed to the client, you could dynamically (at run time) mix-in a Fax or EMail class to handle the transmission of the document. This is similar to multiple inheritance as implemented in some other languages, but more flexible because you don't need to know in advance which mixin will be required; different instances of the same class can, if appropriate, mix-in different classes.
When you 'mix-in' another class, what effectively happens is that a new object of the mixed-in class is created, and merged into the original object. The public properties and methods of the mixed-in class now become available in the original object, very much as though they were defined in the original class.
You can mix-in as many other classes as you like; you can even mix in classes from multiple different architectures. For example, you could write (in APL) a FinancialClock class to display the time in London, New York and Singapore. It could mix-in the System Class Window for the display, and the Java class timeZone to handle the different time-zone information.
To use mix-ins, you first create an object (i.e., an instance of your APL class) in the normal way using
Create an instance of Invoice:
inv←⎕new 'Invoice' ⍝ Properties: inv.⎕nl 2 customer invoice_number lines order_number ⍝ Methods: inv.⎕nl 3 SetStatus
Mix class Fax into the Invoice object:
inv.⎕mixin 'Fax' ⍝ Properties and methods now include those of Fax class: inv.⎕nl 2 cover_page ⍝ <--- From Fax class customer fax_number ⍝ <--- From Fax class invoice_number lines order_number inv.⎕nl 3 Send ⍝ <--- From Fax class SetStatus
You can mix-in further classes in the same way.
Although in this example we have mixed-in the Fax class (using dot notation) after creating the original object, in many cases the natural place to do this will be in the Constructor of the original class. If you do that, the mix-in facility effectively becomes like multiple inheritance in some other languages.
Mixing-in an external class
You can mix an external class (.Net. Java, Ruby, or a built-in APLX system class) in to your APL class in the same way. In this case, you need to provide a left argument to
'java' inv.⎕mixin 'java.util.Date' ⎕box inv.⎕nl 3 Send SetStatus UTC after before clone compareTo equals getClass getDate getDay getHours getMinutes getMonth getSeconds getTime getTimezoneOffset getYear hashCode notify notifyAll parse setDate setHours setMinutes setMonth setSeconds setTime setYear toGMTString toLocaleString toString wait inv.toLocaleString 20-Mar-2009 11:43:03
Referencing the mixed-in object directly
Sometimes you may need to access the underlying object which has been merged into your APL object. For this, you need a reference to the underlying object. You can get this in two ways:
jd←'java' inv.⎕mixin 'java.util.Date' jd.⎕classname java:java.util.Date
(2) You can use the system method
my_mixins←inv.⎕mixins my_mixins [Fax] [java:Date] my_mixins.⎕classname java:java.util.Date
Search order and over-riding a method
When a member of the class is referenced (either using dot notation, or as unadorned symbols when running methods of the class), APLX will use the following search order to find the named symbol:
It follows from this that you can 'over-ride' a property or method from a mixed-in class; if your own APL class defines a member of the same name as a member of the mixed-in class, the APL version will be the one which is accessed; the mixed-in version will be hidden.
However, you can still call the mixed-in version by accessing it directly using the object reference returned either when it is created (explicit result of
∇r←toString  ⍝ String representing invoice  r←'Invoice number ',(⍕invoice_number),' dated ',inv.⎕mixins.toString  ∇ ⍝ Insert toString as a method into class Invoice: 'Invoice' ⎕ic 'toString' 1 inv.toString Invoice number 11345301 dated Fri Mar 20 11:57:32 GMT 2009
Removing mixins from an object
The System Method
inv.⎕mixins [Fax] [java:Date] inv.⎕unmix inv.⎕mixins 1 1 inv.⎕mixins inv.⎕nl 3 SetStatus toString
Note that you don't normally need to do this; the mixins will be deleted automatically when the object which owns them is deleted.
Copyright © 1996-2010 MicroAPL Ltd