Problem using Interfce

Ali Çehreli acehreli at yahoo.com
Mon May 14 12:15:32 PDT 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 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



More information about the Digitalmars-d-learn mailing list