Monday, December 15, 2008

Composite Oriented Programming Part 2

I made a slightly more complicated version of the hello world example. This time I made two composite implementations of a Speaker interface.

public interface Speaker
{
public void setSpeech(char[] speech);

public char[] speak();
}

Then I changed how the data is handled as I didn't want two different templates, HelloData and ByeData. So I made a PropertiesMixin template which contains a simple way to set and get properties as char[]s.

public template PropertiesMixin()
{
private char[][char[]] properties;

public void set(char[] name, char[] value)
{
properties[name] = value;
}

public char[] get(char[] name, char[] defaultValue = null)
{
if (name in properties)
{
return properties[name];
}
return defaultValue;
}
}

This can be used to add properties support to a class. There is room for improvement, for example some how use the tango.text.Properties class to save and load the properties.

Then the real meat are the new HelloMixin and ByeMixin, which handles the heavy lifting.

public template HelloMixin()
{
private static const char[] HELLO = "hello";

mixin PropertiesMixin;

public void setSpeech(char[] speech)
{
set(HELLO, speech);
}

public char[] speak()
{
return get(HELLO);
}
}

public template ByeMixin()
{
private static const char[] BYE = "bye";

mixin PropertiesMixin;

public void setSpeech(char[] speech)
{
set(BYE, speech);
}

public char[] speak()
{
return get(BYE);
}
}

I've mixed in the PropertiesMixin for both of them, and then implemented the Speaker interface functions using properties. We could even have a default speech very easily, if needed.

The composite classes are very simple as they do not contain any functionality whatsoever.

public class HelloSpeaker : Speaker
{
mixin HelloMixin;
}

public class ByeSpeaker : Speaker
{
mixin ByeMixin;
}

I've put the setting of the speeches in the main function of the program, where the composites are created, to better demonstrate the usage of the Speaker interface.

public void main()
{
Speaker hello = new HelloSpeaker();
hello.setSpeech("Hello, World!");
Stdout(hello.speak()).newline;

Speaker bye = new ByeSpeaker();
bye.setSpeech("Bye, World!");
Stdout(bye.speak()).newline;
}

I'm pretty impressed about how easy it is to implement complex objects using mixins. Next I need to look into a more complicated version. Something like Fredrik Kalseth has done here.

Until then you can find the new code here.