www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Delegation of interfaces

reply Mahe <maheweb web.de> writes:
Hi,

I like multi inheritance, but all modern programming languages prohibit it. So
I accept single inheritance. But with single inheritance you often delegate
interface implementation to some other internal objects of the class. Only some
special functions of the interface are threaded explicitly. So I think this
delegation could be automated.

For example

interface IList
{
	void add( object o );
	void remove( object o);
	int size();
}

class ArrayList : I List
{
	void add( object o )
	{
	 	/* something */
	}
	void remove( object o)
	{
	 	/* something */
	}
	int size()
	{
	 	/* something */
	}
}

}

class Componet
{
	/* something */
}

class ComponetWithSubComponent : Componet  , IList
{
	/* something*/
	ArrayList internalList;

	void add( object o )
	{
		/* check if o is an legal argument,
	  else throw an exception  */
	...
	...
	internalList.add( o );
	}

	void remove( object o)
	{
		internalList. remove ( o );
	}

	int size()
	{
		return internalList. size ( );
	}		
}

 
Here the functions "ComponetWithSubComponent.remove( object o )" and
"ComponetWithSubComponent.size( object o )" are simple delegations to the
member "internalList". It would be nice if you can leave out the function
"remove" and "size" in "ComponetWithSubComponent" and only write something like

delegate interface  IList to internalList

So, all interface functions of "IList" that are not defined in class
"ComponetWithSubComponent" are automatically delegated to "internalList".
So also compiler optimizations are possible.
Jul 19 2007
parent reply BCS <ao pathlink.com> writes:
You can plug functionality into a class with a mixin. This avoids having 
a inner class just to implement an interface.


|interface IList
|{
|    void add( object o );
|    void remove( object o);
|    int size();
|}
|
|template IListImp()
|{
|    /* somthing */
|    void add( object o )
|    {
|         /* something */
|    }
|    void remove( object o)
|    {
|         /* something */
|    }
|    int size()
|    {
|         /* something */
|    }
|}
|
|class ArrayList : IList
|{
|    mixin IListImp!();
|}
|
|class Componet
|{
|    /* something */
|}
|
|class ComponetWithSubComponent : Componet , IList
|{
|    mixin IListImp!();
|}

also the direct chaining can be bundled up like this:

|template IListImp(alias inner)
|{
|    void add( object o )
|    {
|         inner.add(o)
|    }
|    void remove( object o)
|    {
|         inner.remove(o)
|    }
|    int size()
|    {
|         return inner.size()
|    }
|}
|
|class ComponetWithSubComponent : Componet , IList
|{
|    ArrayList internalList;
|    mixin IListImp!(internalList);
|}

what I want is to be able to make a template the would be able to implement 
any interface by getting a list of functions from the type.

DMD should be able to inline some of this away even now.

If that isn't what you are looking for, then I'm missing something.
Jul 19 2007
next sibling parent Regan Heath <regan netmail.co.nz> writes:
BCS wrote:
 You can plug functionality into a class with a mixin. This avoids having 
 a inner class just to implement an interface.
 
 
 |interface IList
 |{
 |    void add( object o );
 |    void remove( object o);
 |    int size();
 |}
 |
 |template IListImp()
 |{
 |    /* somthing */
 |    void add( object o )
 |    {
 |         /* something */
 |    }
 |    void remove( object o)
 |    {
 |         /* something */
 |    }
 |    int size()
 |    {
 |         /* something */
 |    }
 |}
 |
 |class ArrayList : IList
 |{
 |    mixin IListImp!();
 |}
 |
 |class Componet
 |{
 |    /* something */
 |}
 |
 |class ComponetWithSubComponent : Componet , IList
 |{
 |    mixin IListImp!();
 |}
 
 also the direct chaining can be bundled up like this:
 
 |template IListImp(alias inner)
 |{
 |    void add( object o )
 |    {
 |         inner.add(o)
 |    }
 |    void remove( object o)
 |    {
 |         inner.remove(o)
 |    }
 |    int size()
 |    {
 |         return inner.size()
 |    }
 |}
 |
 |class ComponetWithSubComponent : Componet , IList
 |{
 |    ArrayList internalList;
 |    mixin IListImp!(internalList);
 |}
 
 what I want is to be able to make a template the would be able to 
 implement any interface by getting a list of functions from the type.
 
 DMD should be able to inline some of this away even now.
 
 If that isn't what you are looking for, then I'm missing something.
Those are some very clever solutions, I reckon they need to go on a wiki or something. That said, I wonder if there is some merit in having syntactic sugar in the compiler, in the form suggested by the OP to implement what would essentially be the 2nd solution you gave above? In short, should this be a feature? We could continue D's tradition and re-use the 'delegate' keyword! ;) Regan
Jul 20 2007
prev sibling parent reply Mahe <maheweb web.de> writes:
Nice solution BSC,
it even works when you want to add some functionality, e.g. in the “add”
function:

module main;

import std.stdio;

int main()
{
    IList l;
    l = new ArrayList();
    l.add( null );

    writefln(  );

    l = new ComponetWithSubComponent();
    l.add( null );

    getch();
    return 0;
}

interface IList
{
    void add( Object o );
    void remove( Object o);
    int size();
}

class ArrayList : IList
{
    void add( Object o )
    {
         writefln( "ArrayList.add" );
    }
    void remove( Object o)
    {
         writefln( "ArrayList.remove" );
    }
    int size()
    {
         writefln( "ArrayList.size" );
         return 0;
    }
}

class Componet
{
    /* something */
}

template IListImp(alias inner)
{
    void add( Object o )
    {
         inner.add(o);
    }
    void remove( Object o)
    {
         inner.remove(o);
    }
    int size()
    {
         return inner.size();
    }
}
class ComponetWithSubComponent : Componet , IList
{
    this()
    {
        internalList = new ArrayList();
    }

    public void add( Object o )
    {
        writefln( "ComponetWithSubComponent.add" );
        internalList.add( o );
    }

    ArrayList internalList;
    mixin IListImp!(internalList);
}


But it only works if you write the new “add” function before “mixin
IListImp!(internalList) listMixin;” 

class ComponetWithSubComponent : Componet , IList
{
    this()
    {
        internalList = new ArrayList();
    }

    ArrayList internalList;
    mixin IListImp!(internalList);

    public void add( Object o )
    {
        writefln( "ComponetWithSubComponent.add" );
        listMixin.add( o );
    }  
}

This does not work – bug or intended  ?
Jul 20 2007
parent BCS <ao pathlink.com> writes:
Reply to Mahe,

 This does not work – bug or intended  ?
 
The first example I think is by design, e.g. mixins are not the first choice for overloads. second case with swapped order may be a bug though.
Jul 20 2007