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:
On Mon, 14 May 2012 13:08:06 +0200, Stephen Jones <siwe...@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.

Sorry, no edit functionality. I have just been re-reading property syntax and see it is the same as c# getter setter deals. My understanding is that c# getter setters were simply syntactic 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?

Reply via email to