www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - How to 'add' functions to existing type/class/struct/interface...

reply Matthew Ong <ongbp yahoo.com> writes:
Hi All/Walter Bright,

The ability is able to be model and done by JRuby and also Google Go.


Conversions
...
// this function is now available for the object type Sequence. Done 
outside of Sequence.d
func (s Sequence) MyFunction() string {
    //  My Function has access to all the public/internal data of the
    // Sequence here.
}
...
s Sequence;
s.MyFunction(); // now that can be used. Completelty new Function 
outside of Sequence.d

That is some how like JRuby ability to 'add' method into the java final 
String class without really touching that class String.

Interfaces and methods

Since almost anything can have methods attached, almost anything can 
satisfy an
interface. One illustrative example is in the http package, which 
defines the
Handler interface. Any object that implements Handler can serve HTTP 
requests.

It is not just entirely like java interfaces, but java has to somehow, 
code the api in a very strange pattern to support this.

I read from Adam that it is possible and is done within Phobos by D.
Could some one provide some sample code to explain that.

Mixin and Template does not quite fit there I think, in other 


Perhaps that is not the case within D as a limitation. Some code example 
would be really useful.



-- 
Matthew Ong
email: ongbp yahoo.com
May 19 2011
parent reply Adam D. Ruppe <destructionator gmail.com> writes:
 How to 'add' functions to existing type/class/struct/interface...
You don't. It seems to be that this would break encapsulation anyway.
 I read from Adam that it is possible and is done within Phobos by D.
 Could some one provide some sample code to explain that.
Look in std.range for full examples but here's a brief one: void doSomething(T)(T item) if( isMyInterface!T ) { // use item here } template isMyInterface(T) { static if(is(typeof( // write some code to test the interface here ))) enum bool isMyInterface = true; else enum bool isMyInterface = false; } You can also use the template straight up, though that's less structured: auto doSomething(T)(T obj) { // write whatever you want here using obj // it won't compile if the obj doesn't match the used functions } and automating the isMyInterface detection. Kenju Hara wrote an adaptTo function that does something like this: interface Interface { void foo(); } class A { // note it doesn't list the interface here void foo(); } void func(Interface i) { } A a = new A(); func(adaptTo!Interface(a)); I don't think this has been committed to Phobos yet though.
May 19 2011
next sibling parent Matthew Ong <ongbp yahoo.com> writes:
On 5/19/2011 11:23 PM, Adam D. Ruppe wrote:
 How to 'add' functions to existing type/class/struct/interface...
You don't. It seems to be that this would break encapsulation anyway.
This block of comments is totally not related to this thread, but just to set the record straight. Not entirely. Only data that you deem safe are expose. Go does not have public/private keyword, but they uses first letter of the Identifier of Functions or Variables to define encapsulation(strange+implied). Uppercase first letter = Public. lowercase first letter = Private.
 I read from Adam that it is possible and is done within Phobos by D.
 Could some one provide some sample code to explain that.
Look in std.range for full examples but here's a brief one:
Ok. Thanks.
 void doSomething(T)(T item) if( isMyInterface!T ) {
       // use item here
 }
 template isMyInterface(T) {
       static if(is(typeof(
             // write some code to test the interface here
... Do not know what is done here because I am new.
       )))
           enum bool isMyInterface = true;
       else
           enum bool isMyInterface = false;
 }
Because I am new to D, That is a very strange syntax to me. I suppose the std.range example may give more clarity.
 You can also use the template straight up, though that's less
 structured:

 auto doSomething(T)(T obj) {
       // write whatever you want here using obj
       // it won't compile if the obj doesn't match the used functions
 }
This example is more like a static generics in Java for me. But it is a form of the polymorphic ability. It does not add

 and automating the isMyInterface detection. Kenju Hara wrote
 an adaptTo function that does something like this:

 interface Interface {
      void foo();
 }


 class A { // note it doesn't list the interface here
       void foo();
 }

 void func(Interface i) { }


 A a = new A();

 func(adaptTo!Interface(a));


 I don't think this has been committed to Phobos yet though.
This last example fits the Go interfaces example the best. I think, but there is no code for adaptTo(T). There is no clear idea how this is done. From what I can see Go is doing is like in C/C++: 1) using structure to define the data-type. // Class Object is more expensive. 2) static functions that bind to that structure datatype. Such static functions can be define within the LIB or introduced as new functions outside the library. 3) using some form of function pointer to call those static functions. -- Matthew Ong email: ongbp yahoo.com
May 20 2011
prev sibling parent Matthew Ong <ongbp yahoo.com> writes:
On 5/19/2011 11:23 PM, Adam D. Ruppe wrote:
 How to 'add' functions to existing type/class/struct/interface...
You don't. It seems to be that this would break encapsulation anyway.
Not entirely. As seen within JRuby and Go. JRuby shown that the methods defined within java.lang.String are not corrupted and the new functions can also be entirely independent to String. But that is done with a lot of runtime plumbing within the JRuby engine. I think they injected some bytecode using BSH to do that without touching the String.class file in JVM. Hence, I suspected it has nothing to do with breaking a library's encapsulation. Not too sure about Go as it was designed from ground up to do this. This block of comments is totally not related to this thread, but just to set the record straight. ---------------------------------------------------------------------- Only data that you deem safe are expose. Go does not have public/private keyword, but they uses first letter of the Identifier of Functions or Variables to define encapsulation(strange+implied). Uppercase first letter = Public. lowercase first letter = Private. ----------------------------------------------------------------------
 I read from Adam that it is possible and is done within Phobos by D.
 Could some one provide some sample code to explain that.
Look in std.range for full examples but here's a brief one:
Ok. Thanks.
 void doSomething(T)(T item) if( isMyInterface!T ) {
       // use item here
 }
 template isMyInterface(T) {
       static if(is(typeof(
             // write some code to test the interface here
... Do not know what is done here because I am new...
       )))
           enum bool isMyInterface = true;
       else
           enum bool isMyInterface = false;
 }
Because I am new to D, That is a very strange syntax to me. I suppose the std.range example may give more clarity.
 You can also use the template straight up, though that's less
 structured:

 auto doSomething(T)(T obj) {
       // write whatever you want here using obj
       // it won't compile if the obj doesn't match the used functions
 }
This example is more like a static generics in Java for me. But it is a form of the polymorphic ability. It does not add

 and automating the isMyInterface detection. Kenju Hara wrote
 an adaptTo function that does something like this:

 interface Interface {
      void foo();
 }


 class A { // note it doesn't list the interface here
       void foo();
 }

 void func(Interface i) { }


 A a = new A();

 func(adaptTo!Interface(a));


 I don't think this has been committed to Phobos yet though.
This last example fits the Go interfaces example the best. I think, but there is no code for adaptTo(T). There is no clear idea how this is done. From what I can see Go is doing is like in C/C++: 1) using structure to define the data-type. // Class Object is more expensive. 2) static functions that bind to that structure datatype. Such static functions can be define within the LIB or introduced as new functions outside the library. 3) using some form of function pointer to call those static functions. Hey Adam, you are one of the most experience D person that does give solid answer to experience developers from other language. Thanks for the answer clarifying this. -- Matthew Ong email: ongbp yahoo.com
May 20 2011