How to dynamically call class virtual method dynamically

Frustrated Who at where.com
Tue Apr 1 16:10:30 PDT 2014


On Tuesday, 1 April 2014 at 19:52:47 UTC, Steven Schveighoffer 
wrote:
> On Tue, 01 Apr 2014 15:00:17 -0400, Frustrated <Who at where.com> 
> wrote:
>
>> On Tuesday, 1 April 2014 at 12:20:06 UTC, Steven Schveighoffer 
>> wrote:
>>> On Tue, 01 Apr 2014 03:31:41 -0400, Frustrated 
>>> <Who at where.com> wrote:
>>>
>>>> Basically in programming to interfaces I need to decide to 
>>>> call a virtual method of an object if it exists else call a 
>>>> final method in the interface:
>>>>
>>>> interface A
>>>> {
>>>>    static final void foo() { ... }
>>>> }
>>>>
>>>> class B : A
>>>> {
>>>>    void bar() { ... }     // optional
>>>> }
>>>>
>>>> class C : B
>>>> {
>>>>    void bar() { ... }     // optional
>>>> }
>>>>
>>>> void main()
>>>> {
>>>>    A a = new B;  // or new C;
>>>>
>>>>    // if a.bar exists call it, else call foo
>>>>    // code should work independent of the classes. (there 
>>>> might be more)
>>>> }
>>>>
>>>> The point of the code is simply to allow the class to 
>>>> implement bar optionally but provide default behavior with 
>>>> foo. I need a way to dynamically determine if bar exists and 
>>>> fall back on foo. This should be possible.
>>>>
>>>> e.g., suppose
>>>>
>>>> class B : A { }
>>>>
>>>> then I would like to b.bar() to actually call A.foo() (since 
>>>> bar doesn't exist in b).
>>>>
>>>> I guess the exist way would be to create an opDispatch and 
>>>> have it call foo if bar is passed. This works great and does 
>>>> everything I need it to except requires adding the code in 
>>>> the class which I can't have. Also I'm not sure how it would 
>>>> work with virtual methods.
>>>
>>> Detecting whether bar exists can only happen at compile time, 
>>> since an instance of A has no mechanism to detect whether it 
>>> has bar. D does not have very good runtime introspection, 
>>> that would have to be built into the TypeInfo struct (the 
>>> mechanism exists to do it, but it has never been used for 
>>> that).
>>>
>>> You could use this templates, but that would only work if the 
>>> type of the derived class is known at compile time.
>>>
>>> This problem could easily be solved by virtual methods with 
>>> default implementation.
>>>
>>> -Steve
>>
>> It seems logical to me that I should be able to achieve what I 
>> what.
>>
>> Suppose I have an object cast to it's interface:
>>
>> A a = new B;
>>
>> when I call a.This() it will call the method in the interface. 
>> Either This is a virtual method or a final method. Suppose it 
>> is a Final method since if it is virtual there is no problem.
>>
>> Now suppose B implements That as a virtual method that doesn't 
>> exist in A.
>>
>> Since a IS a B, That exists in it's vtable. I should be able 
>> to call it:
>>
>> a.That(); // Calls B's That().
>
> There is no definition for B's vtable according to A. It just 
> looks like an array of void pointers.
>
> In other words, there's no possible way, without knowing B's 
> type structure, to know which entry in the vtable is 'That'.
>
>> Of course this doesn't work directly because That() is not 
>> part of the interface. Regardless though, it still exists:
>>
>> (cast(B)a).That(); // Works
>
> Because you have (at runtime) determined that a actually IS a 
> 'B'.
>
>> But the only problem is that the cast(B) is required and is a 
>> trick to get the compiler to do what I want.
>
> It's not a "trick", it's a runtime check. It basically is 
> saying "if a is actually a B, then call B.That, otherwise 
> segfault"
>
>> But we know that a is of type B.
>
> The compiler/runtime does not know that.
>
>> e.g., typeof(cast(Object)a) returns B, right?
>
> You are thinking of typeid. But the runtime information does 
> not contain any way to figure out which location 'That' is at.
>
> What you are really looking for is runtime introspection, 
> similar to Java or C#. D has the capability, but it has not 
> been implemented. We only have compile-time introspection.
>
>> I could be mistaken but isn't `A a = new B` just a facade and 
>> a really is of type B?
>
> a is of type A, and it points at an instance of B.
>
>> If so, isn't there a way to get the true type of a at runtime? 
>> If so, then can't we cast a to its true type at runtime and 
>> access its members properly?
>
> You can get at B's typeinfo, but that doesn't contain a way to 
> call arbitrarily named functions.
>
>> e.g., suppose truecast(a) returns a as the actual object that 
>> a was created as(in this case B, not A). Then 
>> truecast(a).That() would work.
>
> With the correct implementation of RTInfo inside object.di, you 
> could possibly make this work. It would be kind of cool. It 
> would be a TON of work to make this a reality.
>
> -Steve

Here is a basic outline of a possible approach. I do not believe 
it is the best way


import std.stdio, std.cstream;

interface A
{	
     public final void opDispatch(string m)()
     {
		opDispatchImpl(m);
     }

     protected bool opDispatchImpl(string m);
     // void bar() { writeln("hello"); } // possible but name 
conflict
}

class B : A
{
	void bar() { writeln("asdfasdf"); }

	override bool opDispatchImpl(string m)
	{
		if (m == "bar") bar();
		return false;
	}

}

void main()
{
	
	A a = new B;
	B b = new B;

	a.bar();     // Wow, A doesn't have a bar yet we call it?!?!
	b.bar();

	din.getc();
}

Note that a does not have a bar() but yet it is called. 
opDispatch on the interface passes it down to the class. This is 
messy and not very robust(how to handle general 
functions(arbitrary parameters and return types easily). Note 
that bar could be final in all cases(no vtable necessary but 
slow).

Essentially opDispatch would implement a vtable look up(the if's) 
but based on the names of the methods.

If D's vtable's contained the signatures of the functions it 
would be somewhat easy to do all this without having to clutter 
up the types with dispatching(but it would be slower because one 
would have to search the right function).

D would have to allow us to call a function in a dynamic way(no 
checking) similar to dynamic in C#.

I imagine one could make such a vtable at compile time and do the 
searching. Look up the methods by classname then methodname 
should be easy enough(they would be string lookups).







More information about the Digitalmars-d-learn mailing list