View mode: basic / threaded / horizontal-split · Log in · Help
May 14, 2012
Problem using Interfce
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
Re: Problem using Interfce
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
Re: Problem using Interfce
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
Re: Problem using Interfce
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 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.
May 14, 2012
Re: Problem using Interfce
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 
>> <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);
>>    }
>> }
>> /
>
> 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?
May 14, 2012
Re: Problem using Interfce
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 avail

Yeah, 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
Re: Problem using Interfce
On 05/14/2012 11:49 AM, Stephen Jones wrote:

> 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?

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 15, 2012
Re: Problem using Interfce
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 16, 2012
Re: Problem using Interfce
On Monday, 14 May 2012 at 20:27:37 UTC, Ali Çehreli wrote:
> On 05/14/2012 11:49 AM, Stephen Jones wrote:
>
> > 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?
>
> It is the same with D but the compiler can optimize out the 
> function call in cases where that is possible.
>
> Ali

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.
May 16, 2012
Re: Problem using Interfce
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
« First   ‹ Prev
1 2
Top | Discussion index | About this forum | D home