On Tuesday, 1 April 2014 at 19:52:47 UTC, Steven Schveighoffer
wrote:
On Tue, 01 Apr 2014 15:00:17 -0400, Frustrated <[email protected]>
wrote:
On Tuesday, 1 April 2014 at 12:20:06 UTC, Steven Schveighoffer
wrote:
On Tue, 01 Apr 2014 03:31:41 -0400, Frustrated
<[email protected]> 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).