Composition OOP là gì

InheritanceEdit

An example in C++ follows:

class Object { public: virtual void update[] { // no-op } virtual void draw[] { // no-op } virtual void collide[Object objects[]] { // no-op } }; class Visible : public Object { Model* model; public: virtual void draw[] override { // code to draw a model at the position of this object } }; class Solid : public Object { public: virtual void collide[Object objects[]] override { // code to check for and react to collisions with other objects } }; class Movable : public Object { public: virtual void update[] override { // code to update the position of this object } };

Then, suppose we also have these concrete classes:

  • class Player - which is Solid, Movable and Visible
  • class Cloud - which is Movable and Visible, but not Solid
  • class Building - which is Solid and Visible, but not Movable
  • class Trap - which is Solid, but neither Visible nor Movable

Note that multiple inheritance is dangerous if not implemented carefully, as it can lead to the diamond problem. One solution to avoid this is to create classes such as VisibleAndSolid, VisibleAndMovable, VisibleAndSolidAndMovable, etc. for every needed combination, though this leads to a large amount of repetitive code. C++ solves the diamond problem of multiple inheritance by allowing virtual inheritance.

Composition and interfacesEdit

The C++ examples in this section demonstrate the principle of using composition and interfaces to achieve code reuse and polymorphism. Due to the C++ language not having a dedicated keyword to declare interfaces, the following C++ example uses "inheritance from a pure abstract base class". For most purposes, this is functionally equivalent to the interfaces provided in other languages, such as Java and C#.

Introduce an abstract class named VisibilityDelegate, with the subclasses NotVisible and Visible, which provides a means of drawing an object:

class VisibilityDelegate { public: virtual void draw[] = 0; }; class NotVisible : public VisibilityDelegate { public: virtual void draw[] override { // no-op } }; class Visible : public VisibilityDelegate { public: virtual void draw[] override { // code to draw a model at the position of this object } };

Introduce an abstract class named UpdateDelegate, with the subclasses NotMovable and Movable, which provides a means of moving an object:

class UpdateDelegate { public: virtual void update[] = 0; }; class NotMovable : public UpdateDelegate { public: virtual void update[] override { // no-op } }; class Movable : public UpdateDelegate { public: virtual void update[] override { // code to update the position of this object } };

Introduce an abstract class named CollisionDelegate, with the subclasses NotSolid and Solid, which provides a means of colliding with an object:

class CollisionDelegate { public: virtual void collide[Object objects[]] = 0; }; class NotSolid : public CollisionDelegate { public: virtual void collide[Object objects[]] override { // no-op } }; class Solid : public CollisionDelegate { public: virtual void collide[Object objects[]] override { // code to check for and react to collisions with other objects } };

Finally, introduce a class named Object with members to control its visibility [using a VisibilityDelegate], movability [using an UpdateDelegate], and solidity [using a CollisionDelegate]. This class has methods which delegate to its members, e.g. update[] simply calls a method on the UpdateDelegate:

class Object { VisibilityDelegate* _v; UpdateDelegate* _u; CollisionDelegate* _c; public: Object[VisibilityDelegate* v, UpdateDelegate* u, CollisionDelegate* c] : _v[v] , _u[u] , _c[c] {} void update[] { _u->update[]; } void draw[] { _v->draw[]; } void collide[Object objects[]] { _c->collide[objects]; } };

Then, concrete classes would look like:

class Player : public Object { public: Player[] : Object[new Visible[], new Movable[], new Solid[]] {} // ... }; class Smoke : public Object { public: Smoke[] : Object[new Visible[], new Movable[], new NotSolid[]] {} // ... };

Video liên quan

Chủ Đề