Code below shows that I would achieve:

///// fire.d
alias void delegate() EventHandler;

class Event(T)
{
    private T[] _events;

    public void opOpAssign(string op)(T param) if (op == "~")
    {
        _events ~= param;
    }

    public void opCall(ParamType ...)(ParamType params)
    {
        this.emit(params);
    }

    protected void emit(ParamType ...)(ParamType params)
    {
        foreach (event; _events)
            event(params);
    }
}

mixin template AddEvent(DelegateType, string member)
{
    private Event!DelegateType _eventObserver;

    @property auto get()
    {
        if (_eventObserver is null)
            _eventObserver = new Event!DelegateType();

        return _eventObserver;
    }

    void doEventObserver(ParamType ...)(ParamType params)
    {
        mixin (member ~ "()(params);");
    }

    mixin ("alias get " ~ member ~ ";");
    mixin ("alias doEventObserver do" ~ member ~ ";");
}

class Fire
{
    public mixin AddEvent!(EventHandler, "click");
}

class DoubleFire
{
    private Event!EventHandler _click;


    public this()
    {
        _click = new Event!EventHandler();
    }

    @property public Event!EventHandler click()
    {
        return _click;
    }

    public void doClick(ParamType ...)(ParamType params)
    {
        click()(params);
    }
}


///// water.d
import std.stdio;

import fire;

class Water : Fire
{

}

void main()
{
    Fire element;

    element = new Fire();
    element.click  ~= () { writeln("Fire!");  };
    element.click()(); // Not needed with DIP 23

    element = new Water();
    element.click ~= () { writeln("Water!"); };
    element.click()(); // Not needed with DIP 23

    DoubleFire df = new DoubleFire();
    df.click ~= () { writeln("Double Fire!"); };
    df.doClick(); // Workaround

    element.doclick(); // Workaround
}

///// Output

Fire!
Water!
Double Fire!
Water!


Thanks)

Reply via email to