January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 30 January 2014 at 17:11:24 UTC, Steven
Schveighoffer wrote:
> On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated <c1514843@drdrb.com> wrote:
>
>
>> Essentially what it boils down to is treating interfaces like
>> classes that have no fields). To avoid the diamond problem simply
>> always choose the method that is not from the interface(since it
>> is "default"), which is done naturally with the vtable.
>
> It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation.
>
> -Steve
Right, this was my original point and why I thought there was
already entries for the interface in the vtable(since I seemed to
have called some function that did nothing when it should have).
It seems so simple and offers some benefit(would at the very
least stop requiring one to implement a class every time they
want test a design. When programming to interfaces and using some
type of factory it makes even more sense.
It then could also be used to test is something is
implemented(possibly for versioning).
e.g.,
interface A
{
void hasSomeFeature() { assert(0, "Not implemented yet"); }
}
Someone can come along and implement the feature and you(the
interface) knows it's implemented if it doesn't assert, set a
flag, or whatever.
Are you 100% sure no default space is created for the vtable?
(trying to reconcile why that case I mentioned worked. I'll try
to throw an example up... may have just been coincidence I didn't
get a segfault)
|
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frustrated | On Thu, 30 Jan 2014 12:30:04 -0500, Frustrated <c1514843@drdrb.com> wrote: > On Thursday, 30 January 2014 at 17:11:24 UTC, Steven > Schveighoffer wrote: >> On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated <c1514843@drdrb.com> wrote: >> >> >>> Essentially what it boils down to is treating interfaces like >>> classes that have no fields). To avoid the diamond problem simply >>> always choose the method that is not from the interface(since it >>> is "default"), which is done naturally with the vtable. >> >> It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. >> >> -Steve > > Right, this was my original point and why I thought there was > already entries for the interface in the vtable(since I seemed to > have called some function that did nothing when it should have). I think your original example should not have happened. Either there was a bug in the runtime, compiler, or your memory :) > > It seems so simple and offers some benefit(would at the very > least stop requiring one to implement a class every time they > want test a design. When programming to interfaces and using some > type of factory it makes even more sense. This is a misunderstanding, you still need to declare a class, because an interface is not a concrete type. But if there are default implementations for all the interface functions, you don't need to implement any of them! > > It then could also be used to test is something is > implemented(possibly for versioning). > > e.g., > > interface A > { > void hasSomeFeature() { assert(0, "Not implemented yet"); } > } > > Someone can come along and implement the feature and you(the > interface) knows it's implemented if it doesn't assert, set a > flag, or whatever. > > Are you 100% sure no default space is created for the vtable? > (trying to reconcile why that case I mentioned worked. I'll try > to throw an example up... may have just been coincidence I didn't > get a segfault) I didn't write the compiler, so I'm not 100%, but I'm 99% sure :) -Steve |
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 30 January 2014 at 17:38:26 UTC, Steven Schveighoffer wrote: > On Thu, 30 Jan 2014 12:30:04 -0500, Frustrated <c1514843@drdrb.com> wrote: > >> On Thursday, 30 January 2014 at 17:11:24 UTC, Steven >> Schveighoffer wrote: >>> On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated <c1514843@drdrb.com> wrote: >>> >>> >>>> Essentially what it boils down to is treating interfaces like >>>> classes that have no fields). To avoid the diamond problem simply >>>> always choose the method that is not from the interface(since it >>>> is "default"), which is done naturally with the vtable. >>> >>> It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation. >>> >>> -Steve >> >> Right, this was my original point and why I thought there was >> already entries for the interface in the vtable(since I seemed to >> have called some function that did nothing when it should have). > > I think your original example should not have happened. Either there was a bug in the runtime, compiler, or your memory :) > Well, as usual, it is almost surely user error. I can't reproduce it so we'll just go with that. >> >> It seems so simple and offers some benefit(would at the very >> least stop requiring one to implement a class every time they >> want test a design. When programming to interfaces and using some >> type of factory it makes even more sense. > > This is a misunderstanding, you still need to declare a class, because an interface is not a concrete type. But if there are default implementations for all the interface functions, you don't need to implement any of them! > No, the point is, if all methods are defined, there is no need to create the class. Why create an empty class to instantiate it when the compiler can do it for you and you can instantiate the interface? This is what I mean by treating the interface as a class because for all purposes it is. (an interface is just an abstract container but it doesn't have to be) Again, all this could be done by the compiler internally by creating a class to back an interface and add it to the vtable. Instantiating the interface just returns that class. Calling a member on the interface's object calls the member of that class, who's body is provided in the interface definition. I can do this now, the whole point is I don't like code duplication! ;) interface A { void foo() { writeln("me"); } void bar(); } class _A // created internally by compiler { void foo() { writeln("me"); } // added by compiler copied from A void bar() { assert(0, "error"); } // added by compiler } A a = new A; // reinterpreted by compiler as A a = new _A; a.foo(); // prints me a.bar(); // asserts e.g., all we would see is interface A { void foo() { writeln("me"); } void bar(); } which is much nicer on the eyes and about half the code. One may argue that this blurs the lines between a class an interface but it doesn't. It can still have multiple inheritance but easily provide a default way to deal with stuff. Remember, the whole point of interfaces was to solve diamond problem. They also now provide the "contract"... I'm just trying to get them to provide the "contract" with default behavior. |
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frustrated | On Thu, 30 Jan 2014 13:06:30 -0500, Frustrated <c1514843@drdrb.com> wrote: > On Thursday, 30 January 2014 at 17:38:26 UTC, Steven > Schveighoffer wrote: >> This is a misunderstanding, you still need to declare a class, because an interface is not a concrete type. But if there are default implementations for all the interface functions, you don't need to implement any of them! >> > > No, the point is, if all methods are defined, there is no need to > create the class. Why create an empty class to instantiate it > when the compiler can do it for you and you can instantiate the > interface? This is what I mean by treating the interface as a > class because for all purposes it is. (an interface is just an > abstract container but it doesn't have to be) > > Again, all this could be done by the compiler internally by > creating a class to back an interface and add it to the vtable. > Instantiating the interface just returns that class. Calling a > member on the interface's object calls the member of that class, > who's body is provided in the interface definition. > > I can do this now, the whole point is I don't like code > duplication! ;) > > interface A > { > > void foo() { writeln("me"); } > void bar(); > } > > class _A // created internally by compiler > { > void foo() { writeln("me"); } // added by compiler copied > from A > void bar() { assert(0, "error"); } // added by compiler > } http://dlang.org/phobos/std_typecons.html#.BlackHole -Steve |
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thu, 30 Jan 2014 13:16:21 -0500, Steven Schveighoffer <schveiguy@yahoo.com> wrote: > > http://dlang.org/phobos/std_typecons.html#.BlackHole Sorry, black hole just does nothing. it's white hole you want: http://dlang.org/phobos/std_typecons.html#.WhiteHole -Steve |
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 30 January 2014 at 17:11:24 UTC, Steven
Schveighoffer wrote:
> On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated <c1514843@drdrb.com> wrote:
>
>
>> Essentially what it boils down to is treating interfaces like
>> classes that have no fields). To avoid the diamond problem simply
>> always choose the method that is not from the interface(since it
>> is "default"), which is done naturally with the vtable.
>
> It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation.
>
> -Steve
But what if you want to provide some default behavior? We are not
dealing with abstract classes here.
Since there is currently no way to do what I am saying no
"solution" will be adequate unless it fulfills the behavior.
(again, it's not like we can't accomplish basically the same
thing, the point is mainly about simplification)
The question was about if there was any innate reason why this
type of behavior couldn't be accomplish using the vtable. I'm
assuming there is none and it could easily be done? (the compiler
just has to reserve the space and setup the pointers to the
functions?)
|
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frustrated | On Thu, 30 Jan 2014 14:58:42 -0500, Frustrated <c1514843@drdrb.com> wrote:
> On Thursday, 30 January 2014 at 17:11:24 UTC, Steven
> Schveighoffer wrote:
>> On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated <c1514843@drdrb.com> wrote:
>>
>>
>>> Essentially what it boils down to is treating interfaces like
>>> classes that have no fields). To avoid the diamond problem simply
>>> always choose the method that is not from the interface(since it
>>> is "default"), which is done naturally with the vtable.
>>
>> It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation.
>>
>> -Steve
>
> But what if you want to provide some default behavior? We are not
> dealing with abstract classes here.
>
> Since there is currently no way to do what I am saying no
> "solution" will be adequate unless it fulfills the behavior.
>
> (again, it's not like we can't accomplish basically the same
> thing, the point is mainly about simplification)
>
> The question was about if there was any innate reason why this
> type of behavior couldn't be accomplish using the vtable. I'm
> assuming there is none and it could easily be done? (the compiler
> just has to reserve the space and setup the pointers to the
> functions?)
The interface defines the vtable, the class contains a value for that vtable.
If you imagine an interface vtable like this:
interface A
{
void foo();
}
=>
struct A_vtbl
{
void function() foo;
}
Note the default value is NULL.
When you create a class that inherits, it's class info contains an A_vtbl:
class B : A
{
void foo() {writeln("hi";}
}
=>
struct B_typeinfo
{
A_vtbl a_interface = {&B.foo};
}
And when you call foo on an instance of A, it uses the vtable, knowing that the layout is A_vtbl.
(this is simplistic, the real thing is more complex to explain, it's somewhere on the docs).
What I'm saying is, if you give a default to the function foo, then our straw-man A_vtbl looks like this:
struct A_vtbl
{
void function() foo = A.default_foo;
}
And when you create B_typeinfo, if you haven't defined foo, it just points at that default foo (of course, you have to fill in B.foo, and for that, you actually have to do a thunk to convert to the interface I think, but this is not hard).
But it's important to note that A does not define an instance of A_vtbl, just the layout! You still need a concrete class to get a vtable instance to point at.
-Steve
|
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 30 January 2014 at 20:17:23 UTC, Steven
Schveighoffer wrote:
> On Thu, 30 Jan 2014 14:58:42 -0500, Frustrated <c1514843@drdrb.com> wrote:
>
>> On Thursday, 30 January 2014 at 17:11:24 UTC, Steven
>> Schveighoffer wrote:
>>> On Thu, 30 Jan 2014 11:58:15 -0500, Frustrated <c1514843@drdrb.com> wrote:
>>>
>>>
>>>> Essentially what it boils down to is treating interfaces like
>>>> classes that have no fields). To avoid the diamond problem simply
>>>> always choose the method that is not from the interface(since it
>>>> is "default"), which is done naturally with the vtable.
>>>
>>> It's simpler than that. A function is a block of code. A vtable entry points to a block of code. Just point the vtable entry at the block of code that is the default implementation.
>>>
>>> -Steve
>>
>> But what if you want to provide some default behavior? We are not
>> dealing with abstract classes here.
>>
>> Since there is currently no way to do what I am saying no
>> "solution" will be adequate unless it fulfills the behavior.
>>
>> (again, it's not like we can't accomplish basically the same
>> thing, the point is mainly about simplification)
>>
>> The question was about if there was any innate reason why this
>> type of behavior couldn't be accomplish using the vtable. I'm
>> assuming there is none and it could easily be done? (the compiler
>> just has to reserve the space and setup the pointers to the
>> functions?)
>
> The interface defines the vtable, the class contains a value for that vtable.
>
> If you imagine an interface vtable like this:
>
> interface A
> {
> void foo();
> }
>
> =>
>
> struct A_vtbl
> {
> void function() foo;
> }
>
> Note the default value is NULL.
>
> When you create a class that inherits, it's class info contains an A_vtbl:
>
> class B : A
> {
> void foo() {writeln("hi";}
> }
>
> =>
>
> struct B_typeinfo
> {
> A_vtbl a_interface = {&B.foo};
> }
>
> And when you call foo on an instance of A, it uses the vtable, knowing that the layout is A_vtbl.
>
> (this is simplistic, the real thing is more complex to explain, it's somewhere on the docs).
>
> What I'm saying is, if you give a default to the function foo, then our straw-man A_vtbl looks like this:
>
> struct A_vtbl
> {
> void function() foo = A.default_foo;
> }
>
> And when you create B_typeinfo, if you haven't defined foo, it just points at that default foo (of course, you have to fill in B.foo, and for that, you actually have to do a thunk to convert to the interface I think, but this is not hard).
>
> But it's important to note that A does not define an instance of A_vtbl, just the layout! You still need a concrete class to get a vtable instance to point at.
>
> -Steve
But what I think you are failing to realize is that regardless
that foo is defined in an interface, since foo does not use this,
it does not depend on the object, so it does not need an
object(for all practical purposes it is a static function but of
course must take an object as the first parameter so it is
compatible as a member function).
Also, regardless that it is an interface, doesn't mean it can't
have a concrete vtable to work with.
The fact is that a vtable is more complex because it has the
ability to call functions defined in a base class. In this case a
"base" interface.
Just because something doesn't exist there now doesn't mean it
can't exist.
Answer me this
class A { void foo() { } }
class B : A { }
B b = new B;
b.foo();
are you telling me there are actually two foo functions? or does
b actually call A's foo passing it the object b e.g., the call
made is actually foo(b);
If so, then what if A is an interface? (by interface, I am
talking about one that has a vtable created for it's members)
interface A { void foo() { } }
class B : A { }
B b = new B;
b.foo();
Whats the difference? Absolutely nothing but your interpretation
of what an interface is.
This is all about semantics. If you want to think of an interface
as some idealized abstract compile time object that doesn't exist
at run time and has no vtable then so be it. But that doesn't
mean it has to be and I'm just saying it is limiting.
Obviously the difference between the two above is that the
compiler does not allow multiple inheritance w.r.t, to classes,
and does not allow fields in interfaces, etc... but these rules
can still be enforced on a class THAT HAS A VTABLE.
I think you still keep trying to fit the square peg in the round
hole. I'm not talking about what the compiler does... we know the
above code as I intend it does not work.
|
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Frustrated | On Thu, 30 Jan 2014 15:57:06 -0500, Frustrated <c1514843@drdrb.com> wrote: > On Thursday, 30 January 2014 at 20:17:23 UTC, Steven > Schveighoffer wrote: >> But it's important to note that A does not define an instance of A_vtbl, just the layout! You still need a concrete class to get a vtable instance to point at. > > But what I think you are failing to realize is that regardless > that foo is defined in an interface, since foo does not use this, > it does not depend on the object, so it does not need an > object(for all practical purposes it is a static function but of > course must take an object as the first parameter so it is > compatible as a member function). But what if it does need an object? interface A { void foo() { bar();} // need 'this' to call bar void bar(); } > Also, regardless that it is an interface, doesn't mean it can't > have a concrete vtable to work with. > > The fact is that a vtable is more complex because it has the > ability to call functions defined in a base class. In this case a > "base" interface. > > Just because something doesn't exist there now doesn't mean it > can't exist. Keep in mind that an interface vtable exists as part of an object. The compiler knows this, and performs thunks when necessary. > Answer me this > > class A { void foo() { } } > class B : A { } > > B b = new B; > b.foo(); > > are you telling me there are actually two foo functions? or does > b actually call A's foo passing it the object b e.g., the call > made is actually foo(b); There is one function, but two vtables, one for A, and one for B. Both point at the same function. > If so, then what if A is an interface? (by interface, I am > talking about one that has a vtable created for it's members) > > interface A { void foo() { } } > class B : A { } > > B b = new B; > b.foo(); > > Whats the difference? Absolutely nothing but your interpretation > of what an interface is. The difference is, now there is only one vtable, and one interface vtable inside B. A has no vtables. If you do this: A a = new B; a now points at the interface struct *inside B's object*. When you call a.foo, it does this: 1. It looks up in the interface vtable for A that's specific for B (accessed via the interface struct in the object itself) to get the function to call. 2. Included in the interface vtable struct is an offset to add so the 'this' pointer actually points at the object itself instead of the interface struct. > This is all about semantics. If you want to think of an interface > as some idealized abstract compile time object that doesn't exist > at run time and has no vtable then so be it. But that doesn't > mean it has to be and I'm just saying it is limiting. An interface instance and an object instance are two VERY different things, and are handled differently by the compiler. -Steve |
January 30, 2014 Re: Interfaces allow member definitions? | ||||
---|---|---|---|---|
| ||||
Posted in reply to Steven Schveighoffer | On Thursday, 30 January 2014 at 21:16:05 UTC, Steven Schveighoffer wrote: > On Thu, 30 Jan 2014 15:57:06 -0500, Frustrated <c1514843@drdrb.com> wrote: > >> On Thursday, 30 January 2014 at 20:17:23 UTC, Steven >> Schveighoffer wrote: >>> But it's important to note that A does not define an instance of A_vtbl, just the layout! You still need a concrete class to get a vtable instance to point at. >> >> But what I think you are failing to realize is that regardless >> that foo is defined in an interface, since foo does not use this, >> it does not depend on the object, so it does not need an >> object(for all practical purposes it is a static function but of >> course must take an object as the first parameter so it is >> compatible as a member function). > > But what if it does need an object? > > interface A > { > void foo() { bar();} // need 'this' to call bar > void bar(); > } > I've said many times that the functions could not use this. If you are going to go that far then why not allow interfaces to have fields? In this case they would not be any different from classes. >> Also, regardless that it is an interface, doesn't mean it can't >> have a concrete vtable to work with. >> >> The fact is that a vtable is more complex because it has the >> ability to call functions defined in a base class. In this case a >> "base" interface. >> >> Just because something doesn't exist there now doesn't mean it >> can't exist. > > Keep in mind that an interface vtable exists as part of an object. The compiler knows this, and performs thunks when necessary. > >> Answer me this >> >> class A { void foo() { } } >> class B : A { } >> >> B b = new B; >> b.foo(); >> >> are you telling me there are actually two foo functions? or does >> b actually call A's foo passing it the object b e.g., the call >> made is actually foo(b); > > There is one function, but two vtables, one for A, and one for B. Both point at the same function. Yes, and they could point to the function defined in the interface. When they call it, they would pass themselves as this. The methods in the interface do not use this, so it doesn't matter (they could potentially use it but it would require that it always be valid) >> If so, then what if A is an interface? (by interface, I am >> talking about one that has a vtable created for it's members) >> >> interface A { void foo() { } } >> class B : A { } >> >> B b = new B; >> b.foo(); >> >> Whats the difference? Absolutely nothing but your interpretation >> of what an interface is. > > The difference is, now there is only one vtable, and one interface vtable inside B. A has no vtables. If you do this: > > A a = new B; > > a now points at the interface struct *inside B's object*. When you call a.foo, it does this: > > 1. It looks up in the interface vtable for A that's specific for B (accessed via the interface struct in the object itself) to get the function to call. > 2. Included in the interface vtable struct is an offset to add so the 'this' pointer actually points at the object itself instead of the interface struct. > Who says A doesn't have a vtable? That's something that you are forcing on it. You have to get off that if we are ever to make any headway. >> This is all about semantics. If you want to think of an interface >> as some idealized abstract compile time object that doesn't exist >> at run time and has no vtable then so be it. But that doesn't >> mean it has to be and I'm just saying it is limiting. > > An interface instance and an object instance are two VERY different things, and are handled differently by the compiler. > > -Steve Again, you have to get off of what has been defined. You have the mentality exactly the same as those that thought the earth was flat, imaginary numbers were nonsense/useless, man couldn't go to the moon. If you define your knowledge on what you already know what is the point? You just run around in circles.... nothing changes.... you'll just continue believing the earth is flat... |
Copyright © 1999-2021 by the D Language Foundation