I have an interface which is behavioral in the sense that provides some functionality that can be applied to a certain data shape. For example, a hierarchical data structure.
Firstly, let us define the base class
class Base {
virtual void general_functionality() = 0;
virtual void general_functionality1() = 0;
};
Then, I have another abstract class which inherits from Base but it also add a few more interfaces that are specific eg a dynamic hierarchical data structure (data that can be altered by having it synced to a Database for example)
class CommonBaseForDynamicApp : public Base {
virtual void apply_dynamic_logic() = 0;
};
Now let us look at the first implementation where we have a Json based data structure. (implementation code left)
class CommonBaseForJsonDynamicAppImpl1 : public CommonBaseForDynamicApp {
void apply_dynamic_logic() override {};
void general_functionality() override {};
void general_functionality1() override {};
};
And we can have another like Yaml based
class CommonBaseForYamlDynamicAppImpl1 : public CommonBaseForDynamicApp {
void apply_dynamic_logic() override {};
void general_functionality() override {};
void general_functionality1() override {};
};
Now we also want to support Json based data structure where the underlaying data won't be eg externally connected to eg a DB. Therefore, I will now directly inherit from Base
again.
class CommonBaseForJsonStaticApp : public Base {
void general_functionality() override {};// Same impl as CommonBaseForJsonDynamicAppImpl1::general_functionality;
void general_functionality1() override {};// Same impl as CommonBaseForJsonDynamicAppImpl1::general_functionality1;
};
As you can see from above, the design is abit problematic due to the fact that we got duplication of code. Many of the static and dynamic applications overlap.
The first solution I thought of is to make use of virtual inheritance. Here, we implement a class that is directly inherited from Base
class CommonForJson : public Base {
void general_functionality() override {};
void general_functionality1() override {};
};
Then, our static case could directly inherit from that (in this case it does not have to since no additional code is needed).
class CommonBaseForJsonStaticApp : public CommonForJson {
};
For the dynamic case we must inherit from two places namely and make use of virtual inheritance. :
class CommonBaseForJsonDynamicAppImpl : public CommonBaseForDynamicApp, virtual CommonForJson {
void apply_dynamic_logic() override {};
};
While the above will work, I suspect this type of inheritance and tight coupling might create problems in the long run. So I want to ask whether the above issue has alternative design patterns which are more ideal - I assume this problem might have been faced by others as well. We are using c++-20
Same impl as CommonBaseForJsonDynamicAppImpl1::general_functionality
If that's the case, then a core assumption in your class hierarchy is false. That is, the reason why CommonBaseForDynamicApp
uses Base
as a base class is because these two pieces of functionality interact. The fact that you can implement these in the same way is evidence that they don't belong in the same class hierarchy.
It seems clear to me that whatever CommonBaseForDynamicApp
represents, it isn't something that necessarily needs the stuff from Base
. As such, it should not be in the same class hierarchy. Maybe it's something that certain types have rather than something certain types are .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.