digitalmars.D - property magic for inerfaces (please!)
- Hasan Aljudy (56/56) Nov 18 2006 Consider the following hypothetical interface:
- Daniel Keep (17/78) Nov 18 2006 There are two ways of doing this, depending on the situation.
- Reiner Pope (9/14) Nov 18 2006 The problem with both of these solutions is that they are conceptually w...
- Hasan Aljudy (18/33) Nov 18 2006 That's a possible solution, but it's still adds the inconvenience of
- Lionello Lunesu (11/45) Nov 18 2006 What if getChildren() is a costly function, that, say, does an SELECT on...
- Reiner Pope (11/20) Nov 19 2006 But you could apply this sort of argument ("we want to allow people to i...
- Hasan Aljudy (4/27) Nov 19 2006 Yeah, and it's not like the interface is sooo abstract that it doesn't
- Kristian Kilpi (22/55) Nov 19 2006 le
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.
Nov 18 2006
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/
Nov 18 2006
== Quote from Daniel Keep (daniel.keep.lists gmail.com)'s articleThere 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.
Nov 18 2006
Reiner Pope wrote:== Quote from Daniel Keep (daniel.keep.lists gmail.com)'s articleThat'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.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.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 { ... }
Nov 18 2006
"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.
Nov 18 2006
== Quote from Lionello Lunesu (lionello lunesu.remove.com)'s articleWhat 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
Nov 19 2006
Reiner Pope wrote:== Quote from Lionello Lunesu (lionello lunesu.remove.com)'s articleYeah, 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.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
Nov 19 2006
On Sun, 19 Nov 2006 13:27:14 +0200, Reiner Pope = <reiner.pope gmail.REMOVE.com> wrote:=3D=3D Quote from Lionello Lunesu (lionello lunesu.remove.com)'s artic=le=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* =e =declaring all the functions virtual. You want to do getChildren().length becaus=ay =you already know the implementation of getChildren, which is not a fair w==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, ReinerWell 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.
Nov 19 2006