Brain fart - Multiple inheritance

Hi guys,

I was dabbling with MixIns the other day and I found a nice way to mimic multiple inheritance in Coldfusion so I thought it might be handy if I shared.

(this is an extract of an internal document I made for training purposes at work)

One area we have always struggled with in our software base is the possibility to reuse code or functionality without having to duplicate anything.

One popular way of doing this is good old inheritance. Extending a single parent class and therefore inherit its entire behaviour. This is excellent in a lot of cases.

But what if I need the behaviour of two parent classes to be combined? For instance if I have a convenient ‘populate’ method that I came up with at some point that makes it easy to populate my model objects, but I also have this fantastic ‘serialize’ method that I need.
I could put both these methods in one single super class, yes, but in some cases I will only need the ‘populate’ method and the ‘serialize’ is not applicable or vice versa.

What we are really looking for in this case is something know as Multiple Inheritance where we inherit the behaviour of more than one parent:

This is not ‘REAL’ inheritance because the little trick where you use the ‘is a’ sentence no longer applies:

  • ‘SomeModelBean is a CanPopulate’ still kind of applies, however, the sentence ‘SomeModelBean CanPopulate and CanSerialize’ makes more sense.

We also need to ensure a few basic rules when we want to create a system that allows for multiple inheritance:

  • If both parents have overlapping method names, only the first parent should pass the method on.

  • SomeModelBean could still be extending an actual single base-class using the normal default single inheritance and none of the multiple inherited method should override its methods.

For ColdFusion I came up with a MixIn method to get this done. I rely on ColdFusion that allows functions to be passed by reference by default, but when this reference is passed to the scope of another class it actually creates a deep copy instead. This feature makes it possible to come up with a clever construct:

Any class that we want to make available to inherit from in a multi-inheritance set-up will need to extend this base class:

MixInBase.cfc

Here is an example of a multiple inheritance enabled class:

CanTalk.cfc

To mix this into your class:

Dog.cfc

If you want to override the sound:

AngryDog.cfc

And that is basically all there is to it.

Use it or loose it :slight_smile:

Cheers,
Tom Van Schoor

Thanks for the tip Tom. Are you aware of WireBox’s native mixin capabilities? You can mix in any number of .cfm files full of methods with a simple component annotation:

component mixins="/helpers/canSerialize,/helpers/canPopulate"{ }

http://wirebox.ortusbooks.com/content/runtime_mixins/index.html

WireBox also supports virtual inheritance which can be used in combination with regular inheritance to mixin methods from another CFC. The only limitation here is that we currently only allow you runtime inheritance from a single class.

mapPath("model.users.UserService").virtualInheritance("BaseModel");

http://wirebox.ortusbooks.com/content/virtual_inheritance/index.html

Thanks!

~Brad

ColdBox Platform Evangelist
Ortus Solutions, Corp

E-mail: brad@coldbox.org
ColdBox Platform: http://www.coldbox.org
Blog: http://www.codersrevolution.com

Hi Brad,

Yeah I was aware, but sometimes a cfm just does not cut it if you want to get both properties and methods from a unit tested class for instance…

Here is a cool example of where this can be quite powerful:

And yes, no limitation on how many items you want to mix in. As long as you take care that there are no overlapping properties and method names.

Thanks for the feedback!

Cheers,
Tom

Ah i realized that this example could use a bit of explaining…

The class is called CanRollback.cfc and when you mix this in to a command object (Command pattern - Wikipedia) you can register all your DB transactions and whenever needed you can just call command.rollback() and all transactions will be rolled back in reverse order. :wink:

Cheers,
Tom