views:

44

answers:

1

I have a generic items list class to create a more specific listing using it as base class, something like this..

ref class ItemBase { }
ref class ItemA : ItemBase { }
ref class ItemList abstract {
 public:
  virtual void add(ItemBase ^p);
}
ref class ItemListA : ItemList {
 public:
  virtual void add(ItemA ^p) override; // it doesn't works :(
}

I want to restric adding specific type of items in each class.

+2  A: 

The accepted pattern for doing this is making the base class method protected:

ref class ItemBase { }
ref class ItemA : ItemBase { }
ref class ItemList abstract {
 protected:
  virtual void addInternal(ItemBase ^p);
}
ref class ItemListA : ItemList {
 public:
  virtual void add(ItemA ^p){addInternal(p);} 
}

Here is a better solution using generics. Note how we constrain the generic parameter T to ItemBase, to enforce that this collection must only ne used with ItemBase or its subclasses.

ref class ItemBase { };
ref class ItemA : public ItemBase { };

generic <class T>
where T: ItemBase
ref class ItemList abstract {
 public:
     virtual void Add(T p){}
};

ref class ItemListA : ItemList<ItemA^> {
   //no need to override Add here
};

//usage
int main(array<System::String ^> ^args)
{
    ItemListA^ list = gcnew ItemListA();
    list->Add(gcnew ItemA());
}
Igor Zevaka
Won't work, because function parameters are not covariant. The contract for `addInternal` is that it accepts any `ItemBase` object. Derived classes can relax the contract, but they must never refuse to accept arguments that are valid for the base class version. Well ok, it will sort of work the way you are doing it, but if you're going to write wrapper functions you should be using containment and not inheritance. Note that another class can still derive from `ItemListA`, call `addInternal` directly, and break the invariant.
Ben Voigt
I agree, it's a fairly non-sensical example because you would normally make the base class generic. It does however resolve the original issue the OP had, albeit somewhat awkwardly. Perhaps I was a bit rush on declaring it an accepted apttern ;)
Igor Zevaka
It works ! thanks :P
grilix
+1 for code using generics
Ben Voigt