On Mon, 08 Feb 2010 14:36:37 -0500, Andrei Alexandrescu
<[email protected]> wrote:
Don wrote:
Andrei Alexandrescu wrote:
Walter has now implemented final methods in interfaces and also
contracts in interfaces, both of which I think are just awesome.
We figured that essentially he artificially disallows interfaces from
providing bodies for methods. I think that's a gratuitous limitation;
the only distinguishing quality of an interface is that it has no
state. Other than that, interfaces can always offer overridable
functions that by default offer functionality in terms of existing
interface functions. For example:
interface Stack(T)
{
void push(T);
void pop();
@property ref T top();
@property bool empty();
T belowTop()
{
auto t = top;
pop();
auto result = top;
push(t);
}
}
The default implementation of belowTop does a fair amount of work. A
particular implementation might just use that or override it with a
more efficient implementation.
Many more examples can be imagined, but I'm looking for a killer one,
or perhaps a killer counterexample (e.g. when would an
interface-defined method be really bad?)
Your thoughts welcome.
Andrei
I don't understand this. How does belowTop() know how to call top()?
It calls top() through the normal interface mechanism. Inside
belowTop(), this has Stack!T type.
Actually, I think Don has a point here. A virtual function (even on an
interface) is always called with the 'this' pointer, not the interface
pointer. A real example:
interface A
{
int bar();
int foo() { return bar(); }
}
class C : A
{
override int bar() { return 1;}
}
class D : C
{
override int foo() { return 2;}
}
if you have a reference to A, when calling foo, what do you pass as the
this pointer? I think the way it works is an interface call does an
interface lookup to get the 'true' this pointer (this is a quick lookup
since an interface pointer has the offset info at a predetermined
location), so the object pointer is passed into foo. When the actual type
is a D object, a D reference is expected, but when the actual type is a C
object, what is expected?
The compiler cannot tell what the underlying type is, so when the actual
type is a C object, a C reference will be passed in. So in a "default
implementation", there has to be an implicit thunk to convert the type
back into an interface. Basically, the function foo as implemented in A
looks like this:
int foo() {
A __this = cast(A)this; // do a thunk, 'this' is of type Object
return __this.bar(this); // no lookup of this required, so this is the
same as a standard virtual call
}
This severely lowers my taste for this idea. I think a thunk uses a
linear lookup of the interface list at runtime to find the correct
interface.
A way you might be able to get rid of this problem is to compile the
default implementation as if it were a function of the class that
implements the interface. I could probably live with that, but this
feature seems more complicated than it is worth.
-Steve