View mode: basic / threaded / horizontal-split · Log in · Help
November 18, 2006
property magic for inerfaces (please!)
Consider the following hypothetical interface:

interface IPerson
{
    IPerson getFather();
    IPerson getMother();
    IPerson[] getSiblings();
    IPerson[] getChildren();
}

For practical purposes, it would be nice to have some methods defined in 
that interface, such as:

bool hasChildren()
{
    return getChildren().length != 0;
}

but it's not possible to define this method right in the interface. 
(Suppose say we really have to have the thing as an interface and not as 
an abstract class).

A possible solution is to add it to the interface without defining it,

interface IPerson
{
    IPerson getFather();
    IPerson getMother();
    IPerson[] getSiblings();
    IPerson[] getChildren();

    bool hasChildren();
}

while hoping that all classes implemeting this interface would define 
the method in the same way, i.e.
bool hasChildren()
{
    return getChildren().length != 0;
}
The main problem with this is that it's not practical more complicated 
functions.

Another solution is to define the function outside of the interface,

bool hasChildren(IPerson dude)
{
    return dude.getChildren().length != 0;
}

The problem with this is that it doesn't feel quiet right when you use it.
...
IPerson guy = .... //something
..
if( hasChildren(guy) )
{
 ....
}

It would be nice if the compiler would allow you to call this method as 
a property (like with arrays)

if( guy.hasChildren() )
{
 ....
}

Can we have this feature before v1.0?
Basically, a function that takes an interface as a first parameter can 
be considered a property of that interface.
November 19, 2006
Re: property magic for inerfaces (please!)
Hasan Aljudy wrote:
> Consider the following hypothetical interface:
> 
> interface IPerson
> {
>     IPerson getFather();
>     IPerson getMother();
>     IPerson[] getSiblings();
>     IPerson[] getChildren();
> }
> 
> For practical purposes, it would be nice to have some methods defined in
> that interface, such as:
> 
> bool hasChildren()
> {
>     return getChildren().length != 0;
> }
> 
> but it's not possible to define this method right in the interface.
> (Suppose say we really have to have the thing as an interface and not as
> an abstract class).
> 
> A possible solution is to add it to the interface without defining it,
> 
> interface IPerson
> {
>     IPerson getFather();
>     IPerson getMother();
>     IPerson[] getSiblings();
>     IPerson[] getChildren();
> 
>     bool hasChildren();
> }
> 
> while hoping that all classes implemeting this interface would define
> the method in the same way, i.e.
> bool hasChildren()
> {
>     return getChildren().length != 0;
> }
> ...

There are two ways of doing this, depending on the situation.

The first is to have an abstract base class, which allows you to add
partial implementation.

The other is to provide a mixin for the "default" implementation of
certain methods.  For example:

> interface IPerson
> {
>     IPerson getFather();
>     IPerson getMother();
>     IPerson[] getSiblings();
>     IPerson[] getChildren();
>
>     bool hasChildren();
> }
>
> template MPerson
> {
>     bool hasChildren()
>     {
>         return this.getChildren.length != 0;
>     }
> }
>
> class SomePerson : IPerson
> {
>     mixin MPerson;
>
>     // ...
> }

In this case, SomePerson needs to implement the first four methods, but
hasChildren is implemented by the mixin.  Ruby does something similar
for implementing things like comparison operators, sorting, etc.

Of course, extension methods would be *even cooler*, but this works
right now :)

	-- Daniel

-- 
Unlike Knuth, I have neither proven or tried the above; it may not even
make sense.

v2sw5+8Yhw5ln4+5pr6OFPma8u6+7Lw4Tm6+7l6+7D
i28a2Xs3MSr2e4/6+7t4TNSMb6HTOp5en5g6RAHCP  http://hackerkey.com/
November 19, 2006
Re: property magic for inerfaces (please!)
== Quote from Daniel Keep (daniel.keep.lists@gmail.com)'s article
> There are two ways of doing this, depending on the situation.
> The first is to have an abstract base class, which allows you to add
> partial implementation.
> The other is to provide a mixin for the "default" implementation of
> certain methods.
The problem with both of these solutions is that they are conceptually wrong,
since they involve adding hasChildren to the vtbl, meaning it could have any
implementation. What Hasan was asking for was the ability for interfaces to
declare final methods in interfaces, which would mean they can't be overridden.

To achieve this the "proper" way you either need to support final methods in
interfaces or extension methods. Of course, the latter is already partly
implemented, and is a much more powerful feature, so I think it should be added to
D in any case.
November 19, 2006
Re: property magic for inerfaces (please!)
Reiner Pope wrote:
> == Quote from Daniel Keep (daniel.keep.lists@gmail.com)'s article
>> There are two ways of doing this, depending on the situation.
>> The first is to have an abstract base class, which allows you to add
>> partial implementation.
>> The other is to provide a mixin for the "default" implementation of
>> certain methods.

That's a possible solution, but it's still adds the inconvenience of 
having to know which mixins go with the interface whenever you want to 
implement it.

> The problem with both of these solutions is that they are conceptually wrong,
> since they involve adding hasChildren to the vtbl, meaning it could have any
> implementation. What Hasan was asking for was the ability for interfaces to
> declare final methods in interfaces, which would mean they can't be overridden.
> 
> To achieve this the "proper" way you either need to support final methods in
> interfaces or extension methods. Of course, the latter is already partly
> implemented, and is a much more powerful feature, so I think it should be added to
> D in any case.

Maybe final methods would work better ..

Imagine a class that implements IPerson

class Kid : IPerson
{
    ...
}

Without final methods, "Kid" won't really have access to the magic 
properties of IPerson.

Kid k = ...
...
if( k.hasChildren() ) //ops, no such property for class Kid
{
    ...
}
November 19, 2006
Re: property magic for inerfaces (please!)
"Hasan Aljudy" <hasan.aljudy@gmail.com> wrote in message 
news:ejo4sm$h6$1@digitaldaemon.com...
> Consider the following hypothetical interface:
>
> interface IPerson
> {
>     IPerson getFather();
>     IPerson getMother();
>     IPerson[] getSiblings();
>     IPerson[] getChildren();
> }
>
> For practical purposes, it would be nice to have some methods defined in 
> that interface, such as:
>
> bool hasChildren()
> {
>     return getChildren().length != 0;
> }
>
> but it's not possible to define this method right in the interface. 
> (Suppose say we really have to have the thing as an interface and not as 
> an abstract class).
>
> A possible solution is to add it to the interface without defining it,
>
> interface IPerson
> {
>     IPerson getFather();
>     IPerson getMother();
>     IPerson[] getSiblings();
>     IPerson[] getChildren();
>
>     bool hasChildren();
> }
>
> while hoping that all classes implemeting this interface would define the 
> method in the same way, i.e.
> bool hasChildren()
> {
>     return getChildren().length != 0;
> }
> The main problem with this is that it's not practical more complicated 
> functions.

What if getChildren() is a costly function, that, say, does an SELECT on a 
remote database? You would not want it to have that particular 
implementation since it would not need to collect the children first, just 
to check whether there are any.

Unfortunately, the only correct way to work with interfaces *is* declaring 
all the functions virtual. You want to do getChildren().length because you 
already know the implementation of getChildren, which is not a fair way to 
look at it.

L.
November 19, 2006
Re: property magic for inerfaces (please!)
== Quote from Lionello Lunesu (lionello@lunesu.remove.com)'s article
> What if getChildren() is a costly function, that, say, does an SELECT on a
> remote database? You would not want it to have that particular
> implementation since it would not need to collect the children first, just
> to check whether there are any.
> Unfortunately, the only correct way to work with interfaces *is* declaring
> all the functions virtual. You want to do getChildren().length because you
> already know the implementation of getChildren, which is not a fair way to
> look at it.
> L.

But you could apply this sort of argument ("we want to allow people to implement
it differently") everywhere so, by that logic, we shouldn't have final methods,
since there *might* sometime be a reason to reimplement them (and you could even
extend this argument to disallow every function which isn't a class, since none of
them involve a virtual function lookup!). There is a limit to how much flexibility
can be achieved in an API, and it is sometimes useful to final methods. If the
interface expects that getChildren will run in a reasonable time, then it violates
the Liskov Substitution principle if an implementing class takes too long on it.

Cheers,

Reiner
November 19, 2006
Re: property magic for inerfaces (please!)
Reiner Pope wrote:
> == Quote from Lionello Lunesu (lionello@lunesu.remove.com)'s article
>> What if getChildren() is a costly function, that, say, does an SELECT on a
>> remote database? You would not want it to have that particular
>> implementation since it would not need to collect the children first, just
>> to check whether there are any.
>> Unfortunately, the only correct way to work with interfaces *is* declaring
>> all the functions virtual. You want to do getChildren().length because you
>> already know the implementation of getChildren, which is not a fair way to
>> look at it.
>> L.
> 
> But you could apply this sort of argument ("we want to allow people to implement
> it differently") everywhere so, by that logic, we shouldn't have final methods,
> since there *might* sometime be a reason to reimplement them (and you could even
> extend this argument to disallow every function which isn't a class, since none of
> them involve a virtual function lookup!). There is a limit to how much flexibility
> can be achieved in an API, and it is sometimes useful to final methods. If the
> interface expects that getChildren will run in a reasonable time, then it violates
> the Liskov Substitution principle if an implementing class takes too long on it.
> 
> Cheers,
> 
> Reiner

Yeah, and it's not like the interface is sooo abstract that it doesn't 
define anything at all! It does define something; it defines "what" 
should be done.
November 19, 2006
Re: property magic for inerfaces (please!)
On Sun, 19 Nov 2006 13:27:14 +0200, Reiner Pope  
<reiner.pope@gmail.REMOVE.com> wrote:

> == Quote from Lionello Lunesu (lionello@lunesu.remove.com)'s article
>> What if getChildren() is a costly function, that, say, does an SELECT  
>> on a
>> remote database? You would not want it to have that particular
>> implementation since it would not need to collect the children first,  
>> just
>> to check whether there are any.
>> Unfortunately, the only correct way to work with interfaces *is*  
>> declaring
>> all the functions virtual. You want to do getChildren().length because  
>> you
>> already know the implementation of getChildren, which is not a fair way  
>> to
>> look at it.
>> L.
>
> But you could apply this sort of argument ("we want to allow people to  
> implement
> it differently") everywhere so, by that logic, we shouldn't have final  
> methods,
> since there *might* sometime be a reason to reimplement them (and you  
> could even
> extend this argument to disallow every function which isn't a class,  
> since none of
> them involve a virtual function lookup!). There is a limit to how much  
> flexibility
> can be achieved in an API, and it is sometimes useful to final methods.  
> If the
> interface expects that getChildren will run in a reasonable time, then  
> it violates
> the Liskov Substitution principle if an implementing class takes too  
> long on it.
>
> Cheers,
>
> Reiner


Well said.

But why should functions defined in an interface to be final? They could  
be 'copied' to a class creating virtual functions just like mixins do.

This way you could use interfaces to create final functions and default  
implemenations for virtual functions. No need to split an interface to a  
mixin + interface definitions.
Top | Discussion index | About this forum | D home