LennonLam
LennonLam

Reputation: 335

OOP: How to dynamically extend functions in superclass

I have a base class B and 2 derived classes D1, D2.

class B {
    int commonFunc();
    virtual int specifyFunc();
}
class D1 : public B {
    int specifyFunc();
}
class D2 : public B {
    int specifyFunc();
}

Now I meet a requirement that i need to extend my base class function commonFunc(). Since i don't want to modify existing code in base class, i derived another class like:

class B {
    virtual int commonFunc();    // Change to virtual
    virtual int specifyFunc();
}
class B2 : public B {
    int commonFunc();    // A new commonFunc() to meet new requirement
}

However, D1 and D2 cannot use the new commonFunc() in B2 except I modify the inheritance hierarchy.

Here is a possible solution i figured out

class B {
    virtual int commonFunc();
    virtual int specifyFunc();
}
class D1 : public B {
    int specifyFunc();
}
class D2 : public B {
    int specifyFunc();
}
class NewD1 : public D1 {
    int commonFunc();   // Overrided commonFunc() in base class
}
class NewD2 : public D2 { 
    int commonFunc();   // Overrided commonFunc() in base class
}

Since the commonFunc() in NewD1 and NewD2 are exactly the same, this solution involves a poor code-copy

I am looking for any design pattern or solution which can dynamically extend base class without much modification to existing class.

Upvotes: 0

Views: 567

Answers (2)

GFranke
GFranke

Reputation: 237

Interface Design (Program to an interface, not an implementation)

You could avoid such implementation dependencies by using a common interface (pure abstract class) IB. You could change behavior (commonFunc()) by adding new classes (NewB) without changing existing classes.
Clients refer to the common interface and are independent of an implementation.

Decorator Design

If you can't do that or really want do extend the behavior of an object dynamically at run-time, Decorator may help. But Decorator can only add behavior before and/or after performing the old behavior.

See the following UML diagrams (if you aren't sure how to implement, please let me know).

UML Diagram

For further discussion see the GoF Design Patterns Memory for learning object-oriented design & programming / Decorator / Design Principles (Interface Design) at http://w3sdesign.com.

Upvotes: 0

Gnucki
Gnucki

Reputation: 5133

You have several solutions. Inheritance should only be used to factorize code for classes having the same responsability. This means that your class Car shouldn't inherit from a class Logger because you want some logging capabilities. This will determine which solution to choose.

1. D1 and D2 have the same responsability than B

Then a good way to have a more modular inheritance is the pattern decorator. This would allow you to do what you want. Just a little code to have an idea:

class B {
    virtual int commonFunc();
    virtual int specifyFunc();
}

class BDecorator: public B {
    B parent;
    B(B&);
    virtual int commonFunc(); // Implementation forward to parent.
    virtual int specifyFunc(); // Implementation forward to parent.
}
class B2: public BDecorator {
    int commonFunc();
    int specifyFunc();
}
class D1 : public BDecorator {
    int specifyFunc();
}
class D2 : public BDecorator {
    int specifyFunc();
}

// Use:
B b();
B2 b2(b);
D1 d1(b2);

2. D1 and D2 have not the same responsability than B

Then you should use composition instead of inheritance. This means that you should define a pure abstract class D (an interface) and make D1 and D2 inherit from it. Then, in the constructor of B, you can inject a D. (Yes in this solution, you have to change B a little, tell me if this is really a problem.)

class B {
    D d;
    int commonFunc();
    virtual int specifyFunc(); // Do something with d.
    B(D);
}

class D {
    virtual int func();
}
class D1 : public D {
    int func();
}
class D2 : public D {
    int func();
}

// Use with B, but you can use B2 (inheriting from B) instead:
D1 d1();
B b1(d1);

D2 d2();
B b2(d2);

I apologize for my old C++.

Upvotes: 2

Related Questions