TilesWithData
is publicly derived from Tiles
, hence it can be assigned to a (smart or dumb) pointer of type Tiles
(my C++ is a bit rusted, but basically this should be sound)
Tiles *tiles = new TilesWithData();
Disallowing tiles->AddTile(123)
would violate the Liskov Substitution Principle (see here), since a client that has a pointer to a Tiles
instance (be it an actual Tiles
or a TilesWithData
) would not know not to call AddTile
.
If there is a common functionality, you might introduce an abstract base class for both
class Tiles
{
public:
virtual vector<int> GetTiles() = 0;
}
from which you can derive SimpleTiles
class SimpleTiles : public Tiles
{
public:
void AddTile(int x) { tiles_.push_back(x); }
std::vector<int> GetTiles
{
return tiles_;
}
private:
std::vector<int> tiles_;
}
and TilesWithData
class TilesWithData : Tiles
{
public:
void AddTile(int x, double data)
{
tiles_.push_back(x);
data_.push_back(data);
}
std::vector<int> GetTiles
{
return tiles_;
}
std::vector<double> GetData()
{
return data_;
}
private:
// elided
}
This way, the data (internals) of your class is encapsulated and you are free to change the actual internal implementation without breaking the clients of your code. Furthermore, any client, holding a reference to Tiles
can be sure about its capabilities: Getting the list of tiles. Anything further is up to the derivatives.
Remarks: There is still plenty of space for improvements. The Tiles
implementations are neither fish nor meat, they don't provide real logic, but they are neither simple collections. A better way could be abstrac tiles
class Tile
{
public:
virtual void Update() = 0;
}
and a single collection to hold all types derived from Tile
class Tiles
{
public:
void AddTile(std::shared_ptr<Tile> tileToAdd)
{
tiles_.push_back(tileToAdd);
}
void UpdateTiles()
{
for(std::vector<std::shared_ptr<Tile>>:iterator it = tiles_.begin(); it != tiles_.end(); it++)
{
(*it)->Update();
}
}
private:
std::vector<std::shared_ptr<Tile>> tiles_;
}
Now you can implement different types of tiles suited to your needs
class SimpleTile : public Tile
{
public:
SimpleTile(int whatever)
{
// ...
}
void Update()
{
// ...
}
// ...
}
class TileWithData : public Tile
{
public:
TileWithData(int whatever, double data)
{
// ...
data_ = data;
}
void Update()
{
// ...
}
// ...
}
Disclaimer: It might well be that there are some errors in my C++ syntax. If my intention is clear, feel free to edit, otherwith, please leave me a comment.