Call method if declared only
Виталий Фадеев
vital.fadeev at gmail.com
Fri Feb 28 09:25:58 UTC 2020
On Friday, 28 February 2020 at 09:12:38 UTC, Simen Kjærås wrote:
> On Friday, 28 February 2020 at 06:12:37 UTC, Виталий Фадеев
> wrote:
>> Searching solution for idea !
>
> For whatever reason, it seems my attempts at answering this
> earlier has disappeared into the void. Here:
>
> import core.sys.windows.windows;
> import std.stdio;
>
> class Base {
> LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) {
> switch (message) {
> case WM_KEYDOWN:
> return tryCall!"OnWM_KEYDOWN"(wParam, lParam);
> default:
> }
> return 0;
> }
>
> auto tryCall(string name, Args...)(Args args) {
> import std.meta;
>
> alias This = typeof(this);
> alias module_ = __traits(parent, This);
>
> enum isSubclass(T...) = is(T[0] : This);
> alias getModuleMember(string name) =
> __traits(getMember, module_, name);
> enum hasMethod(T) = __traits(hasMember, T, name);
>
> // Get every member in this module
> enum memberNames = __traits(allMembers, module_);
> alias members = staticMap!(getModuleMember,
> memberNames);
>
> // Filter away anything that isn't derived from Base
> alias subclasses = Filter!(isSubclass, members);
>
> // Get rid of anything that doesn't have a method with
> the correct name
> alias subclassesWithMethod = Filter!(hasMethod,
> subclasses);
>
> // Sort them so you get the most derived types first
> alias Types = DerivedToFront!subclassesWithMethod;
>
> // Check for each type if the `this` is an instance of
> that specific one
> static foreach (T; Types) {
> if (cast(T)this !is null) {
> // And look up that method and call it.
> return __traits(getMember, cast(T)this,
> name)(args);
> }
> }
>
> // If `this` is not one of the types with that method,
> return some default value
> return 0;
> }
> }
>
> class Button : Base {
> LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) {
> writeln("WM_KEYDOWN");
> return 0;
> }
> }
>
> unittest {
> Base b1 = new Base();
> Base b2 = new Button();
>
> writeln("Base:");
> b1.On(WM_KEYDOWN, 0, 0);
> writeln("Button:");
> b2.On(WM_KEYDOWN, 0, 0);
> }
>
> Now, this only works for subclasses defined in the same module.
> A possibly better solution would be interfaces:
>
> import core.sys.windows.windows;
> import std.stdio;
>
> class Base {
> LRESULT On(UINT message, WPARAM wParam, LPARAM lParam) {
> switch (message) {
> case WM_KEYDOWN:
> if (cast(IKeyDown)this) {
> return
> (cast(IKeyDown)this).OnWM_KEYDOWN(wParam, lParam);
> }
> default:
> }
> return 0;
> }
> }
>
> interface IKeyDown {
> LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam);
> }
>
> class Button : Base, IKeyDown {
> LRESULT OnWM_KEYDOWN(WPARAM wParam, LPARAM lParam) {
> writeln("WM_KEYDOWN");
> return 0;
> }
> }
>
> unittest {
> Base b1 = new Base();
> Base b2 = new Button();
>
> writeln("Base:");
> b1.On(WM_KEYDOWN, 0, 0);
> writeln("Button:");
> b2.On(WM_KEYDOWN, 0, 0);
> }
>
> --
> Simen
Yes. Thank !
I read it.
Problem is - OS has many messages + user messages... It mean what
interfaces like IKeyDown must me declared. All. Dream on write
less code...
Some like code generation. In message dispatcher. Like this:
import core.sys.windows.windows;
import std.stdio;
import std.traits;
template canOn( T, M )
{
enum string callbackName = "On" ~ __traits( identifier, M
);
static if ( __traits( hasMember, T, callbackName ) )
enum canOn = isCallable!( __traits( getMember, T,
callbackName ) );
else
enum canOn = false;
}
void maybeOn( T, alias M )( T o, M message )
{
enum string callbackName = "On" ~ __traits( identifier, M
);
static if ( canOn!(T, M) )
__traits( getMember, T, callbackName )();
}
void On( T, alias M )( T o, M message )
{
o.maybeOn( message );
}
class Base
{
void Send( T, alias M )( T o, M message )
{
// generate code in dispatcher
// if ( canOn!( T, M ) )
// writeCode(
// q{
// if ( message == WM_KEYUP )
// o.OnWM_KEYUP();
// }
// );
o.On( message );
}
}
class A : Base
{
void OnWM_KEYUP()
{
writeln( "A.OnKey()" );
}
}
void main()
{
auto a = new A();
a.Send( a, WM_KEYUP );
}
Here I have compile error... at
void On( T, alias M )( T o, M message )
Now I reading Template doc for up skill...
Thank!
More information about the Digitalmars-d-learn
mailing list