Thread overview | |||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|
|
May 06, 2013 Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
I have a list of functions which receive values of different types, like in std.concurrency... // example from std.concurrency receive( (int i) { writeln("Received the number ", i);} ); ...although in my case I can probably live by with only accepting objects. I built a list of the handlers and the message classes they accept. My problem is that I don't know how to check if the message I have to dispatch is of the class the handler accepts *or a subclass*. I only managed to check for class equality: if(typeid(msg) == typeHandler.type) { typeHandler.handler(msg); } How can I also accept subclasses? Thanks, Luís |
May 06, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | On Monday, 6 May 2013 at 17:03:20 UTC, Luís Marques wrote: > I have a list of functions which receive values of different types, like in std.concurrency... > > // example from std.concurrency > receive( > (int i) { writeln("Received the number ", i);} > ); > > ...although in my case I can probably live by with only accepting objects. > > I built a list of the handlers and the message classes they accept. My problem is that I don't know how to check if the message I have to dispatch is of the class the handler accepts *or a subclass*. I only managed to check for class equality: > > if(typeid(msg) == typeHandler.type) > { > typeHandler.handler(msg); > } > > How can I also accept subclasses? > > Thanks, > Luís Just cast it - http://dlang.org/expression.html#CastExpression Casting object `foo` to type `Bar` will yield `null` if `foo` is not an instance of a `Bar` or of a subclass of `Bar`. This is particularly usefull combined with a declaration inside an `if` statement: if(auto castedObject = cast(typeHandler.type)msg) { typeHandler.handler(msg); } BTW, for this to work `typeHandler.type` needs to be known at compile-time. |
May 06, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On Monday, 6 May 2013 at 21:20:49 UTC, Idan Arye wrote:
> BTW, for this to work `typeHandler.type` needs to be known at compile-time.
That's the rub. This list of handler is dynamic, so `typeHandler.type` is a TypeInfo, not a compile-time type.
|
May 06, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | On May 6, 2013, at 10:03 AM, "Luís.Marques" <luismarques@gmail.com>"@puremagic.com <luismarques@gmail.com> wrote: > > How can I also accept subclasses? How are the messages stored? std.concurrency uses Variant.convertsTo. |
May 06, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | On Monday, 6 May 2013 at 21:26:03 UTC, Luís Marques wrote:
> On Monday, 6 May 2013 at 21:20:49 UTC, Idan Arye wrote:
>> BTW, for this to work `typeHandler.type` needs to be known at compile-time.
>
> That's the rub. This list of handler is dynamic, so `typeHandler.type` is a TypeInfo, not a compile-time type.
If the type handlers are your own classes, then you can let them check it. Have a method in the handlers that check if an object can be handled by that handler, and use it on each handler until you find one that fits.
|
May 07, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On Monday, 6 May 2013 at 23:53:51 UTC, Idan Arye wrote:
> If the type handlers are your own classes, then you can let them check it. Have a method in the handlers that check if an object can be handled by that handler, and use it on each handler until you find one that fits.
I don't understand. Imagine I have:
class X
{
void handleFoo(Foo msg) { ... }
void handleBar(Bar msg) { ... }
}
I want to register an instance of X to receive messages of type Foo (or subclass) and messages of type Bar (or subclass) in the respective handler methods. Where are you proposing for your check to be implemented?
|
May 07, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Sean Kelly | On Monday, 6 May 2013 at 23:48:11 UTC, Sean Kelly wrote:
> How are the messages stored? std.concurrency uses Variant.convertsTo.
I had looked at Variant.convertsTo but (IIRC) it accepts a type (not a TypeInfo) and in my design I no longer had the type avaliable in the place where I would use the convertsTo, only the TypeInfo.
I dispatch my messages as they come, so I don't store them. I only store the handler info, in the format Tuple!(TypeInfo, handler).
|
May 07, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Luís Marques | On Tuesday, 7 May 2013 at 00:15:06 UTC, Luís Marques wrote:
> On Monday, 6 May 2013 at 23:53:51 UTC, Idan Arye wrote:
>> If the type handlers are your own classes, then you can let them check it. Have a method in the handlers that check if an object can be handled by that handler, and use it on each handler until you find one that fits.
>
> I don't understand. Imagine I have:
>
> class X
> {
> void handleFoo(Foo msg) { ... }
>
> void handleBar(Bar msg) { ... }
> }
>
> I want to register an instance of X to receive messages of type Foo (or subclass) and messages of type Bar (or subclass) in the respective handler methods. Where are you proposing for your check to be implemented?
I assume that `typeHandler` in your original code is *not* of type `X` - since it has a single `handler` method while `X` has two, with different names. That means that at some point, you had to create it - let's assume it's type is called `TypeHandler`. There is either a global function, static method, or constructor where you create a `TypeHandler` and pass to it the delegate you want to register.
Now, if that function/method/constructor is templated - than you already have at compile time the type you want to handle, so you can prepare the check there(anon function?)
If it's not templated - make it templated! You don't have to make the entire `TypeHanler` templated, just the method that creates it. There, you can create an anonymous function that receives `Object` and returns `bool` and all it does is check for type, and you can have a field in `TypeHandler` that keeps that function and uses it to check if it can handle a certain type.
|
May 24, 2013 Re: Dispatching values to handlers, as in std.concurrency | ||||
---|---|---|---|---|
| ||||
Posted in reply to Idan Arye | On Tuesday, 7 May 2013 at 06:19:24 UTC, Idan Arye wrote:
> If it's not templated - make it templated! You don't have to make the entire `TypeHanler` templated, just the method that creates it. There, you can create an anonymous function that receives `Object` and returns `bool` and all it does is check for type, and you can have a field in `TypeHandler` that keeps that function and uses it to check if it can handle a certain type.
Thanks. It took me a while to understand what you meant, but it's working.
|
Copyright © 1999-2021 by the D Language Foundation