digitalmars.D.learn - Problem using Interfce
- Stephen Jones (21/21) May 14 2012 I have a Widget interface which I was hoping would allow me to
- John Chapman (5/27) May 14 2012 Are you compiling with the -property switch? If so, vertStart and
- simendsjo (36/57) May 14 2012 If the language/runtime knows the actual underlying class for the
- Stephen Jones (15/81) May 14 2012 I haven't been clear, vertStart and vertCount are variables not
- Stephen Jones (7/102) May 14 2012 Sorry, no edit functionality. I have just been re-reading
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (6/11) May 14 2012 It is the same with D but the compiler can optimize out the function
- Stephen Jones (13/25) May 15 2012 Thanks Ali for the syntax, some very useful bits and pieces I did
- H. S. Teoh (25/37) May 15 2012 Here:
- H. S. Teoh (31/31) May 15 2012 Gah, I need to proof-read my code before posting. Here's the corrected
- Ary Manzana (3/8) May 16 2012 But in Java you'd also need to cast the Simpson to a specific class if
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (55/91) May 14 2012 Yeah, that is a fundamental example of object oriented design. Thank you...
- Ary Manzana (2/6) May 15 2012 What are the names of those languages?
I have a Widget interface which I was hoping would allow me to subsume a set of classes {Button, Cursor, etc} as being Widgets so I could keep an array of buttons, cursors, etc by initializing them as Widgets. private Widget[] widgets; ... widgets[widx++]=new Button(fmt, unitw, unith, count); ... widgets[widx++]=new Cursor(unitw, unith, count); But when I try to step through the array I cannot access Button or Cursor variables because "Error: no property 'vertStart' for type 'Widget.Widget'": foreach(Widget w; widgets){ glDrawArrays(GL_TRIANGLES, w.vertStart, w.vertCount); } I am used to languages where the w under consideration in any iteration would be known to have been initialized as a Button or Cursor, etc, and the value of vertStart would be found without error. I cannot cast without wrapping everything in if statements. I could use access functions but I would prefer not to incur function overhead. Is there a solution?
May 14 2012
On Monday, 14 May 2012 at 11:08:09 UTC, Stephen Jones wrote:I have a Widget interface which I was hoping would allow me to subsume a set of classes {Button, Cursor, etc} as being Widgets so I could keep an array of buttons, cursors, etc by initializing them as Widgets. private Widget[] widgets; ... widgets[widx++]=new Button(fmt, unitw, unith, count); ... widgets[widx++]=new Cursor(unitw, unith, count); But when I try to step through the array I cannot access Button or Cursor variables because "Error: no property 'vertStart' for type 'Widget.Widget'": foreach(Widget w; widgets){ glDrawArrays(GL_TRIANGLES, w.vertStart, w.vertCount); } I am used to languages where the w under consideration in any iteration would be known to have been initialized as a Button or Cursor, etc, and the value of vertStart would be found without error. I cannot cast without wrapping everything in if statements. I could use access functions but I would prefer not to incur function overhead. Is there a solution?Are you compiling with the -property switch? If so, vertStart and vertCount must be declared with the property attribute. Otherwise invoke them like regular functions, i.e., vertStart() / vertCount().
May 14 2012
On Mon, 14 May 2012 13:08:06 +0200, Stephen Jones <siwenjo gmail.com> wrote:I have a Widget interface which I was hoping would allow me to subsume a set of classes {Button, Cursor, etc} as being Widgets so I could keep an array of buttons, cursors, etc by initializing them as Widgets. private Widget[] widgets; ... widgets[widx++]=new Button(fmt, unitw, unith, count); ... widgets[widx++]=new Cursor(unitw, unith, count); But when I try to step through the array I cannot access Button or Cursor variables because "Error: no property 'vertStart' for type 'Widget.Widget'": foreach(Widget w; widgets){ glDrawArrays(GL_TRIANGLES, w.vertStart, w.vertCount); } I am used to languages where the w under consideration in any iteration would be known to have been initialized as a Button or Cursor, etc, and the value of vertStart would be found without error. I cannot cast without wrapping everything in if statements. I could use access functions but I would prefer not to incur function overhead. Is there a solution?If the language/runtime knows the actual underlying class for the interface, some overhead must occur behind the scenes. This seems more like a design issue. Why doesn't the interface contain vertStart etc? Should you have a base class that contains these? Or another interface? import std.algorithm, std.stdio; interface Widget {} // common widget class SomeWidget : Widget {} interface VerticeWidget : Widget { // Might be drawn property int vertStart(); } class Button : VerticeWidget { property int vertStart() { return 10; } } // only fetch VerticeWidgets property auto verticeWidgets(Widget[] widgets) { return widgets .map!((a) => cast(VerticeWidget)a)() .filter!((a) => a !is null)(); } void main() { Widget[] widgets; widgets ~= new SomeWidget(); widgets ~= new Button(); widgets ~= new SomeWidget(); // this only includes the Button (prints 10), which has vertStart as it derives from VerticeWidget foreach(widget; widgets.verticeWidgets) { writeln(widget.vertStart); } } /
May 14 2012
On Monday, 14 May 2012 at 11:49:21 UTC, simendsjo wrote:On Mon, 14 May 2012 13:08:06 +0200, Stephen Jones <siwenjo gmail.com> wrote:I haven't been clear, vertStart and vertCount are variables not functions: public int vertStart, vertCount=6; A solution that should work is to dump extending the classes and make an array of void pointers that point, some to Button objects, and some to Cursor objects but I do not know the syntax for doing this, or even if it is possible to have an array of pointers pointing at different classes of objects. I should think it should be possible given that, on a 32 bit machine, pointers are all 32 bit ints so it is basically an array of ints that is being created, only those ints contain the address of a bunch of different types of objects. Thankyou simendsjo for the code you provided it has helped on other matters.I have a Widget interface which I was hoping would allow me to subsume a set of classes {Button, Cursor, etc} as being Widgets so I could keep an array of buttons, cursors, etc by initializing them as Widgets. private Widget[] widgets; ... widgets[widx++]=new Button(fmt, unitw, unith, count); ... widgets[widx++]=new Cursor(unitw, unith, count); But when I try to step through the array I cannot access Button or Cursor variables because "Error: no property 'vertStart' for type 'Widget.Widget'": foreach(Widget w; widgets){ glDrawArrays(GL_TRIANGLES, w.vertStart, w.vertCount); } I am used to languages where the w under consideration in any iteration would be known to have been initialized as a Button or Cursor, etc, and the value of vertStart would be found without error. I cannot cast without wrapping everything in if statements. I could use access functions but I would prefer not to incur function overhead. Is there a solution?If the language/runtime knows the actual underlying class for the interface, some overhead must occur behind the scenes. This seems more like a design issue. Why doesn't the interface contain vertStart etc? Should you have a base class that contains these? Or another interface? import std.algorithm, std.stdio; interface Widget {} // common widget class SomeWidget : Widget {} interface VerticeWidget : Widget { // Might be drawn property int vertStart(); } class Button : VerticeWidget { property int vertStart() { return 10; } } // only fetch VerticeWidgets property auto verticeWidgets(Widget[] widgets) { return widgets .map!((a) => cast(VerticeWidget)a)() .filter!((a) => a !is null)(); } void main() { Widget[] widgets; widgets ~= new SomeWidget(); widgets ~= new Button(); widgets ~= new SomeWidget(); // this only includes the Button (prints 10), which has vertStart as it derives from VerticeWidget foreach(widget; widgets.verticeWidgets) { writeln(widget.vertStart); } } /
May 14 2012
On Monday, 14 May 2012 at 18:39:13 UTC, Stephen Jones wrote:On Monday, 14 May 2012 at 11:49:21 UTC, simendsjo wrote:Sorry, no edit functionality. I have just been re-reading sugar which under the hood called standard functions incurring the standard function overhead. Is this the same with D, or does D implement properties using pointers to the required data fields?On Mon, 14 May 2012 13:08:06 +0200, Stephen Jones <siwenjo gmail.com> wrote:I haven't been clear, vertStart and vertCount are variables not functions: public int vertStart, vertCount=6; A solution that should work is to dump extending the classes and make an array of void pointers that point, some to Button objects, and some to Cursor objects but I do not know the syntax for doing this, or even if it is possible to have an array of pointers pointing at different classes of objects. I should think it should be possible given that, on a 32 bit machine, pointers are all 32 bit ints so it is basically an array of ints that is being created, only those ints contain the address of a bunch of different types of objects. Thankyou simendsjo for the code you provided it has helped on other matters.I have a Widget interface which I was hoping would allow me to subsume a set of classes {Button, Cursor, etc} as being Widgets so I could keep an array of buttons, cursors, etc by initializing them as Widgets. private Widget[] widgets; ... widgets[widx++]=new Button(fmt, unitw, unith, count); ... widgets[widx++]=new Cursor(unitw, unith, count); But when I try to step through the array I cannot access Button or Cursor variables because "Error: no property 'vertStart' for type 'Widget.Widget'": foreach(Widget w; widgets){ glDrawArrays(GL_TRIANGLES, w.vertStart, w.vertCount); } I am used to languages where the w under consideration in any iteration would be known to have been initialized as a Button or Cursor, etc, and the value of vertStart would be found without error. I cannot cast without wrapping everything in if statements. I could use access functions but I would prefer not to incur function overhead. Is there a solution?If the language/runtime knows the actual underlying class for the interface, some overhead must occur behind the scenes. This seems more like a design issue. Why doesn't the interface contain vertStart etc? Should you have a base class that contains these? Or another interface? import std.algorithm, std.stdio; interface Widget {} // common widget class SomeWidget : Widget {} interface VerticeWidget : Widget { // Might be drawn property int vertStart(); } class Button : VerticeWidget { property int vertStart() { return 10; } } // only fetch VerticeWidgets property auto verticeWidgets(Widget[] widgets) { return widgets .map!((a) => cast(VerticeWidget)a)() .filter!((a) => a !is null)(); } void main() { Widget[] widgets; widgets ~= new SomeWidget(); widgets ~= new Button(); widgets ~= new SomeWidget(); // this only includes the Button (prints 10), which has vertStart as it derives from VerticeWidget foreach(widget; widgets.verticeWidgets) { writeln(widget.vertStart); } } /
May 14 2012
On 05/14/2012 11:49 AM, Stephen Jones wrote:My which under the hood called standard functions incurring the standard function overhead. Is this the same with D, or does D implement properties using pointers to the required data fields?It is the same with D but the compiler can optimize out the function call in cases where that is possible. Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
May 14 2012
On Monday, 14 May 2012 at 20:27:37 UTC, Ali Çehreli wrote:On 05/14/2012 11:49 AM, Stephen Jones wrote:Thanks Ali for the syntax, some very useful bits and pieces I did not know. I do not want to use property syntax. Form a performance perspective I cannot see any good reason not to simply use an array of pointers to the different objects (buttons, cursor, etc) rather than incurring function overheads. Except for the good reason that I do not know the syntax. Ary: I seem to remember playing around with a Simpsons extending program in Java that did this; you could throw all the different Simpsons into a single Array because they extended "Simpson", and you could walk through the array and each would call their own name. I kind of purposely left the language vague in case I was mistaken.Mysugarwhich under the hood called standard functions incurring thestandardfunction overhead. Is this the same with D, or does Dimplementproperties using pointers to the required data fields?It is the same with D but the compiler can optimize out the function call in cases where that is possible. Ali
May 15 2012
On Wed, May 16, 2012 at 04:24:12AM +0200, Stephen Jones wrote: [...]Thanks Ali for the syntax, some very useful bits and pieces I did not know. I do not want to use property syntax. Form a performance perspective I cannot see any good reason not to simply use an array of pointers to the different objects (buttons, cursor, etc) rather than incurring function overheads. Except for the good reason that I do not know the syntax. Ary: I seem to remember playing around with a Simpsons extending program in Java that did this; you could throw all the different Simpsons into a single Array because they extended "Simpson", and you could walk through the array and each would call their own name. I kind of purposely left the language vague in case I was mistaken.Here: class Simpson { string name; } class Bart : Simpson { this() { name = "Bart Simpson"; } } class Homer : Simpson { this() { name = "Homer Simpson"; } } void main() { Simpson[] simpsons; foreach (simpson; simpsons) { writeln(simson.name); } } T -- PNP = Plug 'N' Pray
May 15 2012
Gah, I need to proof-read my code before posting. Here's the corrected version: class Simpson { string name; } class Bart : Simpson { this() { name = "Bart Simpson"; } } class Homer : Simpson { this() { name = "Homer Simpson"; } } void main() { Simpson[] simpsons = [ new Bart, new Homer ]; foreach (simpson; simpsons) { writeln(simpson.name); } } --T -- My program has no bugs! Only undocumented features...
May 15 2012
On 5/16/12 9:24 AM, Stephen Jones wrote:Ary: I seem to remember playing around with a Simpsons extending program in Java that did this; you could throw all the different Simpsons into a single Array because they extended "Simpson", and you could walk through the array and each would call their own name. I kind of purposely left the language vague in case I was mistaken.But in Java you'd also need to cast the Simpson to a specific class if it contains the fields you are interested it.
May 16 2012
On 05/14/2012 11:40 AM, Stephen Jones wrote:I want an array of different classes of objects.So far, Object[] makes sense.I tried to subsume the differences by extending the classes under a single interface/abstract class/super class (3 different approaches) all to no availYeah, that is a fundamental example of object oriented design. Thank you for showing us some code below. It help a lot.as I could not access the public variables of the instantiated classes while storing them in an array defined by the interface/super class.Makes sense because neither the interface nor the super class has such members. D's polymorphism does not have virtual values (nor does C++'s, the other object oriented language that I know well). Polymorphism is about virtual member functions. What you can do is to force the subclasses provide the data through virtual functions. (An alternative is to use compile-time polymorphism through templates. They provide data virtualization. (See range interfaces like InputRange. For example, the return type of front() is not specified by InputRange. Ranges can be of any type of elements.))interface Widget{ void draw(); } class Button : Widget{ public int vertCount; void draw(){} } class Cursor : Widget{ public int vertCount; void draw(){} } //called from Widget[] widgets; widgets~=new Button(); widgets~=new Cursor(); foreach(Widget w; widgets){ writeln(w.vertCount); } //Error: no property 'vertCount' for type 'Widget.Widget'I've wrapped your code inside void main() and added import std.stdio. Then I got a different error: Error: undefined identifier 'vertCount' But it makes sense, right? Widget does not have vertCount. The following works because the Widget interface mandates that the subclasses provide such a property: import std.stdio; interface Widget{ void draw(); int vertCount() property; // <-- added } class Button : Widget{ public int vertCount_; void draw(){} int vertCount() const property { return vertCount_; } } class Cursor : Widget{ public int vertCount_; void draw(){} int vertCount() const property { return vertCount_; } } void main() { //called from Widget[] widgets; widgets~=new Button(); widgets~=new Cursor(); foreach(Widget w; widgets){ writeln(w.vertCount); } }A solution that should work is to dump extending the classes and make an array of void pointers that point, some to Button objects and some to Cursors but I do not know the syntax for doing this, or even if it is possible to have an array of pointers pointing at different classes of objects. I should think it should be possible given that, on a 32 bit machine, pointers are all 32 bit ints so it is basically an array of ints that is being created, only those ints contain the address of a bunch of different types of objects.Yes, all that is possible too. Ali -- D Programming Language Tutorial: http://ddili.org/ders/d.en/index.html
May 14 2012
On 5/14/12 6:08 PM, Stephen Jones wrote:I am used to languages where the w under consideration in any iteration would be known to have been initialized as a Button or Cursor, etc, and the value of vertStart would be found without error.What are the names of those languages?
May 15 2012