Provide Mixin-like functionality

From The Oxygene Language Wiki
Jump to: navigation, search

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.

Personal tools
Namespaces

Variants
Actions
Navigation
Getting Started
Sections
If you know
More
Toolbox