Problem using Interfce

Stephen Jones siwenjo at gmail.com
Mon May 14 11:39:12 PDT 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 at 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);
>     }
> }
> /

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.



More information about the Digitalmars-d-learn mailing list