www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to dynamically call class virtual method dynamically

reply "Frustrated" <Who where.com> writes:
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.

I've tried using hasMember but since my object is cast to a type 
of Object it never works.
Apr 01 2014
next sibling parent reply "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 1 April 2014 at 07:31:43 UTC, Frustrated 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.

 I've tried using hasMember but since my object is cast to a 
 type of Object it never works.
The traditional OO approach would probably be this: import std.stdio; class A { static final void foo() { writeln("A.foo"); } void bar() { foo(); } } class B : A { override void bar() { writeln("B.bar"); } // optional } class C : A {} void main() { A a0 = new B; // or new C; A a1 = new C; // or new C; a0.bar(); //B.bar a1.bar(); //A.foo } Also, bear in mind that polymorphism is one-way: you can call base class methods through an inherited class reference, but not the other way around. interface A {} class B : A { void bar() {} } void main() { A a = new B; a.bar(); // Error: no property 'bar' for type 'A' }
Apr 01 2014
parent "John Colvin" <john.loughran.colvin gmail.com> writes:
On Tuesday, 1 April 2014 at 09:12:41 UTC, John Colvin wrote:
 Also, bear in mind that polymorphism is one-way: you can call 
 base class methods through an inherited class reference, but 
 not the other way around.
Sorry, I should clarify that: Given an inheritance tree with the base class class at the bottom, calls can always be made down the tree (inheriting class reference calling method in inherited class), but you can only call up the tree via overriden virtual functions (inherited class reference calling inheriting class functions). A new method that isn't present in the base class is by definition not overriding anything in the base class. Therefore you cannot call it from a base class reference, that would mean moving up the inheritance tree.
Apr 01 2014
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 01 Apr 2014 03:31:41 -0400, Frustrated <Who 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
Apr 01 2014
parent reply "Frustrated" <Who where.com> writes:
On Tuesday, 1 April 2014 at 12:20:06 UTC, Steven Schveighoffer 
wrote:
 On Tue, 01 Apr 2014 03:31:41 -0400, Frustrated <Who 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(). 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 But the only problem is that the cast(B) is required and is a trick to get the compiler to do what I want. But we know that a is of type B. e.g., typeof(cast(Object)a) returns B, right? Basically, it should be very easy for the compiler to internally cast a object to it's actual type(since that is contained in the object information, even if it's cast to something else) and call members on it. Of course, I'm not asking for an internal way. I could be mistaken but isn't `A a = new B` just a facade and a really is of type 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? 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. I'm sort of looking for the truecast function/template. Of course, if D doesn't store information about the actual type an object is inside it(which it doesn't AFAIK) then you can't truecast.
Apr 01 2014
next sibling parent "anonymous" <anonymous example.com> writes:
On Tuesday, 1 April 2014 at 19:00:18 UTC, Frustrated wrote:
 A a = new B;
[...] Now suppose B implements That as a virtual method that doesn't exist in A. [...]
 e.g., typeof(cast(Object)a) returns B, right?
No, it's Object. You're looking for typeid which returns a TypeInfo [1] which is runtime information about the type. For classes that's for the most derived one (here: B).
 I could be mistaken but isn't `A a = new B` just a facade and a 
 really is of type 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?
Yes, all true. But you need the target type at compile time to cast.
 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.
When different implementations of A have different Thats, they are not related in any way. And the compiler doesn't know about (possibly future) implementations when working on code that uses just the interface A. So, as far as I can see, truecast(a).That() would have to be a string lookup at runtime. And then the members' types would be dynamic, too, of course. I have no idea how one would go about that. My best guess is that all of D's type system would have to be duplicated at runtime. [1] http://dlang.org/phobos/object.html#TypeInfo
Apr 01 2014
prev sibling parent reply "Steven Schveighoffer" <schveiguy yahoo.com> writes:
On Tue, 01 Apr 2014 15:00:17 -0400, Frustrated <Who 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 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 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
Apr 01 2014
parent "Frustrated" <Who where.com> writes:
On Tuesday, 1 April 2014 at 19:52:47 UTC, Steven Schveighoffer 
wrote:
 On Tue, 01 Apr 2014 15:00:17 -0400, Frustrated <Who 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 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, 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 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).
Apr 01 2014