Reputation: 335
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
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).
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
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