October 02, 2006
An interface is a definition of what *must* be implemented.
An informal interface is a definition of what *could* be implemented.


Java's awt uses the EventListener interface for defining delegate object that can handle UI controls events. The idea is sound, but the implementation has a few flaws.

As it uses events, all methods must be implemented, even if only a single event is of interest. To solve this there are classes for most interfaces that implements all methods with dummy methods, and then you just override what you need. As Jave (And D) does not have multiple inheritance this add another restriction; a delegate object can only handle a single control (or type of control), not a whole window.


In Cocoa (Objecive-C) interfaces are called protocols, different name, same thing. Cocoa also have informal protocols. Event listening protocols are informal. An informal protocol only declare what methods can be implemented, without enforcing them. Not implementing a method simply means that you are not interested int hat event, and the runtime will filter it for you.


I suggest that D add support for informal interfaces using one new keyword, and one new property on all objects.


First methods in interfaces could be marked with he keyword "optional".
Marking a method as optional in an interface will make the interface
informal, just as marking a method abstract in a class will make the
class abstract. A method marked as optional would have two properties:
1. Not even a warning if unimplemented by a class implementing the
interface,
2. Calling the method if unimplemented will do nothing if void, or
return a default value if any other type.
Example:
interface FooDelegate {
   optional void doA();
   optional int askB();
   optional bool isC() = true;
}
All three methods are optional. If doA() is unimplemented nothing will
happen if it is called. if askB() is called then int.init will be
returned. And if isC() is called true will be returned.

If any or all of the three are implemented then it is naturaly up to the implementation to return a proper value.


I attach a file with a longer example fo how it could be useful and work in a real world example.


All problems from Java EventListener paradigm are solved; no need to implement unneeded methods, a delegate object can listen to any number of objects, the object declaring the informal protocol is also free to declare the defaults.


I believe the actual implementation can be very simple. All optional
methods need to be virtual. Optional methods and unimplemented methods
have a NULL entry int the virtual method table. A method dispatch that
normally would be (I use 68k asm for readability :) ):
   move.l 16(a1),a0
   jsr    (a0)
Would now become:
   move.l 16(a1),a0
   beq.s  .skip
   jsr    (a0)
.skip:

A small price to pay, slightly more for non voids. Non default return values, anything different from type.init could be a problem, at least if no access to the original source. The value to use must be available somehow. I have though about letting the optional methods have dumy implementation returning the value, that could then be an expression and not a constant. But I think the testing for implemented methods would become more complex, and calling a method could be more costly that testing for NULL and branch, todays CPUs are good at branch prediction.


Secondly all objects need a new property, a simple property to test for the availability of a method on objects. I suggest this:

public bool implements(method_signature);

And it would be used something along this line:
if (someObject.implements(doSomething(int))) {
   // prepare some costly stuff stuff
   someObject.doSomething(the_costly_result);
}



// Fredrik Olsson


October 02, 2006
Fredrik Olsson schrieb:

I like this idea.

 As Jave (And D) does not have multiple
> inheritance this add another restriction; a delegate object can only handle a single control (or type of control), not a whole window.

Using the *Twin pattern* allow us to model multiple inheritance in languages like D, Java.

A pretty straightforward example in Java  is available at :
http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf

Björn
October 02, 2006
On Mon, 02 Oct 2006 11:42:43 +0300, Fredrik Olsson <peylow@gmail.com> wrote:
> An interface is a definition of what *must* be implemented.
> An informal interface is a definition of what *could* be implemented.
[snip]

I think informal interfaces would be good to have.


> A small price to pay, slightly more for non voids. Non default return
> values, anything different from type.init could be a problem, at least
> if no access to the original source. The value to use must be available
> somehow. I have though about letting the optional methods have dumy
> implementation returning the value, that could then be an expression and
> not a constant. But I think the testing for implemented methods would
> become more complex, and calling a method could be more costly that
> testing for NULL and branch, todays CPUs are good at branch prediction.

Hmm, if an interface would have a 'static vtable' containing addresses for the default functions (that return the default values), then the calling of functions could be done as follows:

1) Get the address of an function to be called to ADDR.
2) If ADDR is not null, goto case 4.
3) Get the address of the corresponding default function of the interface to ADDR.
4) Call the function pointed by ADDR.

(Of course, instead of using static table for function addresses, an interface could have a table pointing to the default values directly.)
October 02, 2006
Fredrik Olsson skrev:
> I attach a file with a longer example fo how it could be useful and work in a real world example.

Some other places where an informal protocol could be useful could be for a URL-request delegate:

interface URLRequestDelegate {
  optional bool acceptUnsignedCertificateForURL(char[] url) = true
  optional void userCredentials(char[] url, out char[] usr,
                                out char[] pwd);
}

Delegating the work would be an easy task, be it automagic, or simply asking the user. And best of all the the delegate informal interfaces would be very clear views of what a class expects of the world. Self-documenting, and easy to model code.


Or as a data source delegate for a table view:

interface CellValue {
  char[] toString();
  optional void drawInRect(Rect);
}

interface TableViewDatasource {
  uint numberOfRows();
  CellValue getCellValue(uint row, uint col);
  optional void setCellValue(CellValue cv, uint row, uint col);
}

Where implementing numberOfRows and getCellValue are required, and would make a read only table. Optionally implementing setCellValue would make the table view editable as well.


// Fredrik Olsson
October 02, 2006
On Mon, 02 Oct 2006 11:57:37 +0200, BLS wrote:

> Fredrik Olsson schrieb:
> 
> I like this idea.
> 
>   As Jave (And D) does not have multiple
>> inheritance this add another restriction; a delegate object can only handle a single control (or type of control), not a whole window.
> 
> Using the *Twin pattern* allow us to model multiple inheritance in languages like D, Java.
> 
> A pretty straightforward example in Java  is available at : http://www.ssw.uni-linz.ac.at/Research/Papers/Moe99/Paper.pdf
> 

The twin pattern seem like an unattractive last resort for someone faced with an existing language and class hierarchy.

If one were designing solutions for the problems related to multiple inheritance, starting from D as it is now, I'd suggest the following:

1) the flexible general solution with a small run-time overhead - allow functions to be written using interfaces as arguments.   Implementation could save space on the stack for what would basically be a run-time determined vtable and lazily fill in the values as needed by the function body;

2) efficient (time) code solution - use templates; for extra safety, allow a mechanism for compile time checking that the template argument actually implements the given interface rather than just having a name collision; member templates would make this more convenient, but are not really necessary.

Top | Discussion index | About this forum | D home