www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Templated Interfaces?

reply Benji Smith <dlanguage benjismith.net> writes:
I've been trying to create a templated interface, and can't figure out 
what I'm doing wrong. Here's the basic example:

interface I(T) {
   public T x();
}

class C(T) : I(T) {
   private T value;
   public this(T val) { this.value = val; }
   public T x() { return value; }
}

void main() {
   I!(char) c = new C!(char)('a');
   char value = c.x();
}

I've tried many many slight variations of this, to try to satisfy the 
compiler, but it always rejects the code, usually by saying something 
like "Interface I used as a type".

Of course! That's because interface I *is* a type.

What am I doing wrong?

--benji
Aug 24 2008
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Benji Smith a écrit :
 I've been trying to create a templated interface, and can't figure out 
 what I'm doing wrong. Here's the basic example:
 
 interface I(T) {
   public T x();
 }
 
 class C(T) : I(T) {

class C(T) : I!(T) {
Aug 24 2008
next sibling parent reply Benji Smith <dlanguage benjismith.net> writes:
Ary Borenszweig wrote:
 Benji Smith a écrit :
 I've been trying to create a templated interface, and can't figure out 
 what I'm doing wrong. Here's the basic example:

 interface I(T) {
   public T x();
 }

 class C(T) : I(T) {

class C(T) : I!(T) {

Very nice! Thanks! Now let's say I want to create an array of those interface instances: interface I(T) { public T x(); } class C(T) : I!(T) { private T value; public this(T val) { this.value = val; } public T x() { return value; } } void main() { I!(char)[] array = new I!(char)[]; array ~ new C!(char)('a'); array ~ new C!(char)('b'); array ~ new C!(char)('c'); char value = array[0].x(); } Now the compiler is complaining about the line where I create the array. It says "Error: new can only create structs, dynamic arrays or class objects, not I[]'s" Obviously, I'm trying to create a dynamic array of interface instances, so I'm not sure what I'm doing wrong. Thanks! --benji
Aug 24 2008
next sibling parent reply Benji Smith <dlanguage benjismith.net> writes:
Simen Kjaeraas wrote:
 You do not need to initialize the the array with the "new I!(char)[]". 
 Just use
 
     I!(char)[] array;
     array ~= new C!(char)('a');
     ...
     char value = array[0].x();

Gotcha. Coming from Java, it's hard getting used to which types require a 'new' and which ones don't. I find the array types especially confusing. Thanks for your help! --benji
Aug 24 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Benji Smith" <dlanguage benjismith.net> wrote in message 
news:g8sih3$7h4$1 digitalmars.com...
 Simen Kjaeraas wrote:
 You do not need to initialize the the array with the "new I!(char)[]". 
 Just use

     I!(char)[] array;
     array ~= new C!(char)('a');
     ...
     char value = array[0].x();

Gotcha. Coming from Java, it's hard getting used to which types require a 'new' and which ones don't. I find the array types especially confusing. Thanks for your help! --benji

Well arrays work _almost_ the same way as in Java, the only difference being that they can change their size. You can either do auto array = new I!(char)[3]; array[0] = .. array[1] = .. array[2] = .. Or just declare it and append stuff. The former will be faster since you'll only do 1 memory allocation instead of n (although the implementation does over-allocate for arrays so that appending is faster, you may not want to depend on that for performance-critical code).
Aug 24 2008
next sibling parent reply Benji Smith <dlanguage benjismith.net> writes:
Jarrett Billingsley wrote:
 Well arrays work _almost_ the same way as in Java, the only difference being 
 that they can change their size.
 
 You can either do
 
 auto array = new I!(char)[3];
 array[0] = ..
 array[1] = ..
 array[2] = ..
 
 Or just declare it and append stuff.  The former will be faster since you'll 
 only do 1 memory allocation instead of n (although the implementation does 
 over-allocate for arrays so that appending is faster, you may not want to 
 depend on that for performance-critical code). 

Huh. I thought that, by putting an integer literal into the array declaration, it'd be declared as a static array rather than a dynamic array. --benji
Aug 24 2008
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Benji Smith a écrit :
 Jarrett Billingsley wrote:
 Well arrays work _almost_ the same way as in Java, the only difference 
 being that they can change their size.

 You can either do

 auto array = new I!(char)[3];
 array[0] = ..
 array[1] = ..
 array[2] = ..

 Or just declare it and append stuff.  The former will be faster since 
 you'll only do 1 memory allocation instead of n (although the 
 implementation does over-allocate for arrays so that appending is 
 faster, you may not want to depend on that for performance-critical 
 code). 

Huh. I thought that, by putting an integer literal into the array declaration, it'd be declared as a static array rather than a dynamic array.

If you put an integer into the array declaration, it *is* declared as a static array. Static array: ------------- auto array = new I!(char)[3]; - array is of type I!(char)[3] (static array) - you cannot append using ~ - you can assign or access using indices - you can initialize it like that or using an array literal Dynamic array: -------------- I!(char)[] array; - array is of type I!(char)[] (dynamic array) - you can append using ~ - you can assign or access using indices - you can initialize it using an array literal
Aug 25 2008
next sibling parent reply Sergey Gromov <snake.scaly gmail.com> writes:
Ary Borenszweig <ary esperanto.org.ar> wrote:
 If you put an integer into the array declaration, it *is* declared as a 
 static array.
 
 Static array:
 -------------
 auto array = new I!(char)[3];
   - array is of type I!(char)[3] (static array)
   - you cannot append using ~
   - you can assign or access using indices
   - you can initialize it like that or using an array literal

import std.stdio; void main() { auto a = new int[3]; writeln(typeof(a).stringof); } prints "int[]". new expression *always* produces a dynamic array. -- SnakE
Aug 25 2008
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Sergey Gromov a écrit :
 Ary Borenszweig <ary esperanto.org.ar> wrote:
 If you put an integer into the array declaration, it *is* declared as a 
 static array.

 Static array:
 -------------
 auto array = new I!(char)[3];
   - array is of type I!(char)[3] (static array)
   - you cannot append using ~
   - you can assign or access using indices
   - you can initialize it like that or using an array literal

import std.stdio; void main() { auto a = new int[3]; writeln(typeof(a).stringof); } prints "int[]". new expression *always* produces a dynamic array.

Ouch. I first wrote I!(char)[3] array = new I!(char)[3]; which compiles, and makes array a static array (you can't append to it). Then, for simplicity, I changed the type to auto... it seems new makes a dynamic array, but then it is implicitly converted to a static one, right?
Aug 25 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ary Borenszweig" <ary esperanto.org.ar> wrote in message 
news:g8vp2l$11nf$1 digitalmars.com...
 Ouch. I first wrote

 I!(char)[3] array = new I!(char)[3];

 which compiles, and makes array a static array (you can't append to it). 
 Then, for simplicity, I changed the type to auto... it seems new makes a 
 dynamic array, but then it is implicitly converted to a static one, right?

No. When you write auto x = Y; it is identical to writing typeof(Y) x = Y; In this case, typeof(new I!(char)[3]) is I!(char)[]. A dynamic array.
Aug 26 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
news:g911lg$ja5$1 digitalmars.com...
 "Ary Borenszweig" <ary esperanto.org.ar> wrote in message 
 news:g8vp2l$11nf$1 digitalmars.com...
 Ouch. I first wrote

 I!(char)[3] array = new I!(char)[3];

 which compiles, and makes array a static array (you can't append to it). 
 Then, for simplicity, I changed the type to auto... it seems new makes a 
 dynamic array, but then it is implicitly converted to a static one, 
 right?

No. When you write auto x = Y; it is identical to writing typeof(Y) x = Y; In this case, typeof(new I!(char)[3]) is I!(char)[]. A dynamic array.

Unless you meant in the non-auto case? In which case I'm kind of surprised the compiler allows it since it normally does not allow you to reassign static arrays.
Aug 26 2008
parent reply Ary Borenszweig <ary esperanto.org.ar> writes:
Jarrett Billingsley a écrit :
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
 news:g911lg$ja5$1 digitalmars.com...
 "Ary Borenszweig" <ary esperanto.org.ar> wrote in message 
 news:g8vp2l$11nf$1 digitalmars.com...
 Ouch. I first wrote

 I!(char)[3] array = new I!(char)[3];

 which compiles, and makes array a static array (you can't append to it). 
 Then, for simplicity, I changed the type to auto... it seems new makes a 
 dynamic array, but then it is implicitly converted to a static one, 
 right?

auto x = Y; it is identical to writing typeof(Y) x = Y; In this case, typeof(new I!(char)[3]) is I!(char)[]. A dynamic array.

Unless you meant in the non-auto case? In which case I'm kind of surprised the compiler allows it since it normally does not allow you to reassign static arrays.

Exactly, I meant in the non-auto case. What's going on there?
Aug 26 2008
parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ary Borenszweig" <ary esperanto.org.ar> wrote in message 
news:g92a1n$a9p$1 digitalmars.com...
 Jarrett Billingsley a écrit :
 "Jarrett Billingsley" <kb3ctd2 yahoo.com> wrote in message 
 news:g911lg$ja5$1 digitalmars.com...
 "Ary Borenszweig" <ary esperanto.org.ar> wrote in message 
 news:g8vp2l$11nf$1 digitalmars.com...
 Ouch. I first wrote

 I!(char)[3] array = new I!(char)[3];

 which compiles, and makes array a static array (you can't append to 
 it). Then, for simplicity, I changed the type to auto... it seems new 
 makes a dynamic array, but then it is implicitly converted to a static 
 one, right?

auto x = Y; it is identical to writing typeof(Y) x = Y; In this case, typeof(new I!(char)[3]) is I!(char)[]. A dynamic array.

Unless you meant in the non-auto case? In which case I'm kind of surprised the compiler allows it since it normally does not allow you to reassign static arrays.

Exactly, I meant in the non-auto case. What's going on there?

OK, I just tried it and stepped through and.. what it seems to do is it allocates an int[] of length 3 on the heap, then slice-copies it into the stack-allocated static array. No reference to the array on the heap is kept. Weird.
Aug 27 2008
prev sibling parent "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Ary Borenszweig" <ary esperanto.org.ar> wrote in message 
news:g8u542$b39$1 digitalmars.com...

 Static array:
 -------------
 auto array = new I!(char)[3];
  - array is of type I!(char)[3] (static array)
  - you cannot append using ~
  - you can assign or access using indices
  - you can initialize it like that or using an array literal

No, new I!(char)[3] is syntactic sugar for new I!(char)[](3) and allocates a 3-element I!(char)[]. Fun fact: it is actually impossible within the syntax of D to allocate a static array on the heap. Not really surprising given the horrible treatment of static arrays in general.
Aug 25 2008
prev sibling parent Bruno Medeiros <brunodomedeiros+spam com.gmail> writes:
Jarrett Billingsley wrote:
 "Benji Smith" <dlanguage benjismith.net> wrote in message 
 news:g8sih3$7h4$1 digitalmars.com...
 Simen Kjaeraas wrote:
 You do not need to initialize the the array with the "new I!(char)[]". 
 Just use

     I!(char)[] array;
     array ~= new C!(char)('a');
     ...
     char value = array[0].x();

Coming from Java, it's hard getting used to which types require a 'new' and which ones don't. I find the array types especially confusing. Thanks for your help! --benji

Well arrays work _almost_ the same way as in Java, the only difference being that they can change their size.

Also, Java's arrays are Object's, D's arrays are not. -- Bruno Medeiros - Software Developer, MSc. in CS/E graduate http://www.prowiki.org/wiki4d/wiki.cgi?BrunoMedeiros#D
Sep 08 2008
prev sibling parent reply Jason House <jason.james.house gmail.com> writes:
Simen Kjaeraas wrote:

 On Sun, 24 Aug 2008 22:20:46 +0200, Benji Smith <dlanguage benjismith.net>
 wrote:
 
 Ary Borenszweig wrote:
 Benji Smith a écrit :
 I've been trying to create a templated interface, and can't figure out
 what I'm doing wrong. Here's the basic example:

 interface I(T) {
   public T x();
 }

 class C(T) : I(T) {


Very nice! Thanks! Now let's say I want to create an array of those interface instances: interface I(T) { public T x(); } class C(T) : I!(T) { private T value; public this(T val) { this.value = val; } public T x() { return value; } } void main() { I!(char)[] array = new I!(char)[]; array ~ new C!(char)('a'); array ~ new C!(char)('b'); array ~ new C!(char)('c'); char value = array[0].x(); } Now the compiler is complaining about the line where I create the array. It says "Error: new can only create structs, dynamic arrays or class objects, not I[]'s" Obviously, I'm trying to create a dynamic array of interface instances, so I'm not sure what I'm doing wrong. Thanks! --benji

You do not need to initialize the the array with the "new I!(char)[]". Just use I!(char)[] array; array ~= new C!(char)('a'); ... char value = array[0].x();

whoa, that's a bad idea! You can not implicitly cast back and forth between interfaces and classes that implement those interfaces; the underlying pointer is not the same. There was a big discussion about this fairly recently on one of the D mailing lists...
Aug 24 2008
parent reply "Jarrett Billingsley" <kb3ctd2 yahoo.com> writes:
"Jason House" <jason.james.house gmail.com> wrote in message 
news:g8sioq$6ul$1 digitalmars.com...

 whoa, that's a bad idea!

 You can not implicitly cast back and forth between interfaces and classes
 that implement those interfaces; the underlying pointer is not the same.
 There was a big discussion about this fairly recently on one of the D
 mailing lists...

No, what he's doing is OK. The trouble only occurs when you try to cast *the array* up or down the inheritance hierarchy.
Aug 24 2008
parent Benji Smith <dlanguage benjismith.net> writes:
Jarrett Billingsley wrote:
 "Jason House" <jason.james.house gmail.com> wrote in message 
 news:g8sioq$6ul$1 digitalmars.com...
 
 whoa, that's a bad idea!

 You can not implicitly cast back and forth between interfaces and classes
 that implement those interfaces; the underlying pointer is not the same.
 There was a big discussion about this fairly recently on one of the D
 mailing lists...

No, what he's doing is OK. The trouble only occurs when you try to cast *the array* up or down the inheritance hierarchy.

Yeah, with the code I'm currently working on, once the objects are in the array, I never again care what the specific class is for each instance, since I'll only be calling the interface methods. --benji
Aug 24 2008
prev sibling parent "Simen Kjaeraas" <simen.kjaras gmail.com> writes:
On Sun, 24 Aug 2008 22:20:46 +0200, Benji Smith <dlanguage benjismith.net>  
wrote:

 Ary Borenszweig wrote:
 Benji Smith a écrit :
 I've been trying to create a templated interface, and can't figure out  
 what I'm doing wrong. Here's the basic example:

 interface I(T) {
   public T x();
 }

 class C(T) : I(T) {


Very nice! Thanks! Now let's say I want to create an array of those interface instances: interface I(T) { public T x(); } class C(T) : I!(T) { private T value; public this(T val) { this.value = val; } public T x() { return value; } } void main() { I!(char)[] array = new I!(char)[]; array ~ new C!(char)('a'); array ~ new C!(char)('b'); array ~ new C!(char)('c'); char value = array[0].x(); } Now the compiler is complaining about the line where I create the array. It says "Error: new can only create structs, dynamic arrays or class objects, not I[]'s" Obviously, I'm trying to create a dynamic array of interface instances, so I'm not sure what I'm doing wrong. Thanks! --benji

You do not need to initialize the the array with the "new I!(char)[]". Just use I!(char)[] array; array ~= new C!(char)('a'); ... char value = array[0].x(); -- Simen
Aug 24 2008