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