Jump to page: 1 24  
Page
Thread overview
"The last feature": overridable methods in interfaces
Feb 08, 2010
Jacob Carlborg
Feb 08, 2010
Trass3r
Feb 08, 2010
Jacob Carlborg
Feb 08, 2010
retard
Feb 08, 2010
Michel Fortin
Feb 08, 2010
retard
Feb 08, 2010
Michel Fortin
Feb 08, 2010
retard
Feb 08, 2010
grauzone
Feb 08, 2010
Walter Bright
Feb 08, 2010
Don
Feb 08, 2010
Don
Feb 08, 2010
dsimcha
February 08, 2010
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
February 08, 2010
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.

What happens when two interfaces implement the same method?  I thought multiple subtyping without multiple inheritance was the raison d'ĂȘtre for interfaces.

-Lars
February 08, 2010
On 2/8/10 06:37, 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 only see two differences with abstract classes: interfaces can't have instance (and class?) variables and you can inherit from multiple interfaces. Am I missing something? Is this really necessary? Isn't abstract classes enough? Does this have similar problems (or the same) as multiple inheritance?


/Jacob Carlborg
February 08, 2010
> I only see two differences with abstract classes: interfaces can't have instance (and class?) variables and you can inherit from multiple interfaces. Am I missing something? Is this really necessary? Isn't abstract classes enough? Does this have similar problems (or the same) as multiple inheritance?
>
>

Yeah, providing default functionality that can be overridden is exactly what abstract classes are for.
Interfaces were introduced to circumvent all those multiple inheritance problems!
February 08, 2010
Lars T. Kyllingstad 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.
> 
> What happens when two interfaces implement the same method?

Ambiguity error.

> I thought multiple subtyping without multiple inheritance was the raison d'ĂȘtre for interfaces.

Interfaces do foster multiple inheritance!

Andrei
February 08, 2010
Trass3r wrote:
>> I only see two differences with abstract classes: interfaces can't have instance (and class?) variables and you can inherit from multiple interfaces. Am I missing something? Is this really necessary? Isn't abstract classes enough? Does this have similar problems (or the same) as multiple inheritance?
>>
>>
> 
> Yeah, providing default functionality that can be overridden is exactly what abstract classes are for.

Abstract classes are a kludge meant to put state in a partially implemented class. I don't think mentioning abstract classes is a counter-argument to defining methods to interfaces.

> Interfaces were introduced to circumvent all those multiple inheritance problems!

Yes; a problem that abstract classes are not solving.


Andrei
February 08, 2010
Jacob Carlborg wrote:
> On 2/8/10 06:37, 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 only see two differences with abstract classes: interfaces can't have instance (and class?) variables and you can inherit from multiple interfaces. Am I missing something? Is this really necessary? Isn't abstract classes enough? Does this have similar problems (or the same) as multiple inheritance?

I think lack of state is indeed the only difference. The multiple
inheritance bit makes all the difference, so I think abstract classes
are not enough. A designer who wants to define some methods in an
interface is forced at design time to choose an abstract class over an
interface, thus severely limiting clients.

Andrei
February 08, 2010
On 2/8/10 14:03, Andrei Alexandrescu wrote:
> Jacob Carlborg wrote:
>> On 2/8/10 06:37, 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 only see two differences with abstract classes: interfaces can't
>> have instance (and class?) variables and you can inherit from multiple
>> interfaces. Am I missing something? Is this really necessary? Isn't
>> abstract classes enough? Does this have similar problems (or the same)
>> as multiple inheritance?
>
> I think lack of state is indeed the only difference. The multiple
> inheritance bit makes all the difference, so I think abstract classes
> are not enough. A designer who wants to define some methods in an
> interface is forced at design time to choose an abstract class over an
> interface, thus severely limiting clients.
>
> Andrei

The obvious solution as I see it would have been using "regular" interfaces and template mixins. But that fails since the mixed in methods can't overload on the already present methods.

Have traits (http://en.wikipedia.org/wiki/Trait_%28computer_science%29) ever been considered?
February 08, 2010
Mon, 08 Feb 2010 07:03:43 -0600, Andrei Alexandrescu wrote:

> Jacob Carlborg wrote:
>> On 2/8/10 06:37, 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 only see two differences with abstract classes: interfaces can't have instance (and class?) variables and you can inherit from multiple interfaces. Am I missing something? Is this really necessary? Isn't abstract classes enough? Does this have similar problems (or the same) as multiple inheritance?
> 
> I think lack of state is indeed the only difference. The multiple inheritance bit makes all the difference, so I think abstract classes are not enough. A designer who wants to define some methods in an interface is forced at design time to choose an abstract class over an interface, thus severely limiting clients.

I really wonder why you're doing this. NIH. Ever heard or Scala and traits? I'm sorry, but you didn't invent this feature - giving some kind of attribution would be honest. I can imagine how this proposal goes forward. Suddenly D 2 gets almost exactly the same feature (+ contracts) as Scala has had for a long time and somehow you get all the credit in the practical (C++/D) PL community.
February 08, 2010
On Mon, 08 Feb 2010 00:37:53 -0500, Andrei Alexandrescu <SeeWebsiteForEmail@erdani.org> 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.

You forgot to return result :)

Also, it should be implemented like this to prevent a problem where a stack with a single element is cleared before an exception is thrown.

T belowTop()
{
  auto t = top;
  pop();
  scope(exit) push(t);
  return top;
}

As another example (not sure if it's "killer"), here is a more useful default method:

T popTop()
{
   scope(success) pop();
   return top;
}

I can see real use for "give me the top, and pop it off at the same time."  Now, if we make popTop final, it's 2 virtual function calls (popTop can be inlined), but if we make it overridable, the default implementation has 3 virtual calls, but can be optimized into 1 virtual call if so desired.  I guess it's a tradeoff between whether you think most implementors will prefer to use some default implementation or most will want to optimize.  But in the case you expect most to optimize, wouldn't you just provide no implementation?  In the case of popTop, it's attractive to say "your stack class only needs to define these few primitives," but it's generally trivial to provide a popTop implementation that is more optimized.

I've seen places where interface documentation says "implement this function like this: ..." which is quite annoying.  final functions solve most of these, I'm not sure if we need another way to do it, but I can't see any reason why it should be disallowed.  The judgement call of whether to provide an overridable implementation and no implementation would be difficult.  I don't see a default-but-overridable implementation being used often.

-Steve
« First   ‹ Prev
1 2 3 4