Provide Mixin-like functionality
This is a Language topic about Oxygene
Language Topics Introduction | Structured Overview | Grammar | Keywords | Functions
There is a simple yet very effective way to get a feature of some other (mainly dynamic) languages that is called "MixIn" to work in Oxygene.
We will use the newest feature addition to interface delegation: implements public
And by that, we will need an interface that defines the members that we want to share across several classes.
Okay, let's start with a basic interface and a default implementation for it:
type ISample = public interface property StringValue : String read write; end; Sample = public class(ISample) public property StringValue : String; end;
Now, if you have a class, that you want to extend with this functionality, you only have to add 2 lines:
type OurTestClass = public class(SomeDescendantClass, ISample) protected property ISampleImpl : ISample := new Sample(); readonly; implements public ISample; end;
What is happening here? We had to put the interface to the inheritance list. And thus make our new class assignable to any reference of that interface type.
var instance := new OurTestClass(); var x : ISample := instance;
But we do not want to implement the interface ourselves. That wouldn't be much mixin-like, would it? ;-)
Instead, we declare a readonly property, that is only visible to descendant classes. And tell the compiler, he should delegate all members of ISample to this property.
The interesting part is the "public" in the implements line. It tells the compiler, he should create public members for anything of that interface.
All this might seem a bit complex and you may not see the benefit of doing so in the first place. ;-)
So let's go back to our source file, where we declare "ISample" and "Sample". Now, we add a new method to both interface and class:
type ISample = public interface property StringValue : String read write; method GetAnInteger : Integer; end; Sample = public class(ISample) public property StringValue : String; method GetAnInteger : Integer; end; implementation method Sample. GetAnInteger : Integer; begin exit 5; end;
Doesn't look too exciting, does it?
Well, let's check our "OurTestClass" if there had been any changes to it...
var instance := new OurTestClass(); var anInteger := instance.GetAnInteger();
Now that is interesting, we have a new method, not only when using the class via an interface reference, but on the class itself as well.
As you can see, every class that is using both interface and default implementation through "implements public", will automatically get any member declared in there.
This allows you to write aspects of classes or records and reuse them, without the need to wrap them explicitly or to be caught in the hell that class inheritance can be.
While it isn't as straightforward as mixins are in other languages, it is very powerful. Allowing you to step in taking full control at any moment and change the implementation for a specific class if you need to. After all it is still just a nice way to implement an interface.