Defining event handlers for function, method, or shared method

tcak via Digitalmars-d-learn digitalmars-d-learn at puremagic.com
Tue Jan 26 11:42:42 PST 2016


On Tuesday, 26 January 2016 at 19:22:58 UTC, Ali Çehreli wrote:
> On 01/26/2016 10:41 AM, tcak wrote:
> > I need/want this class to be able to bind
> > a function, a method, or a shared method. From the
> perspective of class
> > design, there shouldn't be any
> > difference. Its purpose is to let know about the event, not
> to care
> > about how the event
> > handler is designed.
>
> If I understand the problem correctly, an interface can define 
> the interface and a templated class can provide the differences:
>
> import std.stdio;
> import std.algorithm;
>
> interface Event {
>     void start();
>     void stop();
>     void itemAdded( size_t itemIndex );
> }
>
> class ConcreteEvent(alias onStart, alias onStop, alias 
> onItemAdded) : Event {
>     void start() {
>         onStart();
>     }
>
>     void stop() {
>         onStop();
>     }
>
>     void itemAdded(size_t itemIndex) {
>         itemAdded(itemIndex);
>     }
> }
>
> void fooStart() {
> }
>
> void fooStop() {
> }
>
> void fooItemAdded(size_t itemIndex) {
> }
>
> void bar(size_t itemIndex) {
> }
>
> void main() {
>     Event[] events;
>     events ~= new ConcreteEvent!(fooStart, fooStop, 
> fooItemAdded);
>
>     struct S {
>         void memberFunction() {
>         }
>     }
>     auto s = S();
>
>     auto memberClosure(ref S s) {On 01/26/2016 10:41 AM, tcak 
> wrote:
> > I need/want this class to be able to bind
> > a function, a method, or a shared method. From the
> perspective of class
> > design, there shouldn't be any
> > difference. Its purpose is to let know about the event, not
> to care
> > about how the event
> > handler is designed.
>
> If I understand the problem correctly, an interface can define 
> the interface and a templated class can provide differences:
>
> import std.stdio;
> import std.algorithm;
>
> interface Event {
>     void start();
>     void stop();
>     void itemAdded( size_t itemIndex );
> }
>
> class ConcreteEvent(alias onStart, alias onStop, alias 
> onItemAdded) : Event {
>     void start() {
>         onStart();
>     }
>
>     void stop() {
>         onStop();
>     }
>
>     void itemAdded(size_t itemIndex) {
>         itemAdded(itemIndex);
>     }
> }
>
> void fooStart() {
> }
>
> void fooStop() {
> }
>
> void fooItemAdded(size_t itemIndex) {
> }
>
> void bar(size_t itemIndex) {
> }
>
> void main() {
>     Event[] events;
>     events ~= new ConcreteEvent!(fooStart, fooStop, 
> fooItemAdded);
>
>     struct S {
>         void memberFunction() {
>         }
>     }
>     auto s = S();
>
>     auto memberClosure(ref S s) {
>         return () => s.memberFunction();
>     }
>
>     events ~= new ConcreteEvent!(() => memberClosure(s),
>                                  () => writeln("stop"),
>                                  bar);
>
>     events.each!(e => e.stop);
> }
>
> Ali
>
>         return () => s.memberFunction();
>     }
>
>     events ~= new ConcreteEvent!(() => memberClosure(s),
>                                  () => writeln("stop"),
>                                  bar);
>
>     events.each!(e => e.stop);
> }
>
> Ali

Hmm. Your example works fine for functions, but I can't pass a 
method instead of function as alias. Check my example:


import std.socket;

class EventClass{
	public void eventHandlerMethod(){
		writeln("Barking from method");
	}	
}

class Generator(alias eventHandler){
	public void bark(){
		eventHandler();
	}
}

public void eventHandlerFunc(){
	writeln("Barking from function");
}

void main(){
	auto events = new EventClass;

	auto gen1 = new Generator!( eventHandlerFunc )();
	auto gen2 = new Generator!( events.eventHandlerMethod )();

	gen1.bark();
	gen2.bark();
}


Error is given on "auto gen2 = ..." in main function due to 
passing method. I guess because it is runtime normal compile time 
information.

I was looking for something like to be defined in the class 
Generator:

public DelegateOnStart eventOnStart;

So I could set eventOnStart as either function pointer, method 
pointer, or shared method pointer. To be able to support three of 
them, for every event, I need to define another variable, another 
alias, and while calling, check whichever variable (delegate 
pointer) is set, and call that one. I hope I am making it clear 
why it turns into mess.


More information about the Digitalmars-d-learn mailing list