I have a class hierarchy as follows:
struct Arg {
Info someSpecificInfo;
OtherInfo anotherInfo
}
class BaseEvaluator {
public:
BaseEvaluator (Info info) {};
virtual Result evaluate();
}
class SpecificEvaluator1 : public BaseEvaluator {
public:
Derived(Info info): Base(info) {};
Result evaluate();
}
class SpecificEvaluator2: public BaseEvaluator {
public:
SpecificEvaluator2(Info info): Base(info) {};
Result evaluate();
}
However, I currently need to implement two specific Evaluator
classes. One of which uses the Info object (essentially another SpecificEvaluator3
class). However, the other Evaluator
requires the entire Arg
Object.
Now I know that for OOP, I should not be mixing these two classes, and essentially I should change BaseEvaluator
to InfoEvaluator
and create another ArgEvaluator
Class, and maybe both of these can inherit from a base BaseEvaluator
class that has the evalute()
method.
However, the problem is that for these two Evaluator
classes, they largely utilize the same helper methods, where these helper methods utilize the Info member variable. I can visualize my twoEvaluator
classes as follows:
class ArgSpecificEvaluator {
public:
ArgSpecificEvaluator (Arg arg) {};
Result evaluate(); // Implementation Uses OtherInfo
protected:
void helperMethod1(Info);
void helperMethod2(Info);
}
class SpecificEvaluator3 : BaseEvaluator {
public:
SpecificEvaluator3(Info info): {};
Result evaluate();
protected:
void helperMethod1(Info);
void helperMethod2(Info);
}
As you can see there is repeated code for the helperMethods1. Since for ArgSpecificEvaluator
, the helper method is the same when we use arg.Info
instead of just info
as arguments directly. In such case, how to do reconcile this?
Do I switch to just using Arg
for all the classes? The reason I do not do so, is because there is no need to the SpecificEvaluator
classes to even touch OtherInfo
. SpecificEvaluator3
is kind of a special case where it definitely is a type of evaluator, but has characteristics of the ArgSpecificEvaluator
as they both utilize the same helper methods. Initially, the helperMethods() are supposed to have no arguments and utilize the member variable Info
but this scenario is much harder to reconcile so I decided to abstract and put it in the arguments instead.
In a way, what I want to achieve is the Java equivalent of SpecificEvaluator3
inheriting from base class, but implementing an interface with the helper methods. How do I approach this in C ? Multiple Inheritance?
CodePudding user response:
i think what you are trying to achieve is either something like this:
class ArgSpecificEvaluator : public SpecificEvaluator3 {
public:
ArgSpecificEvaluator (Arg arg) : Base(arg.info) {};
Result evaluate() override; // Implementation Uses OtherInfo
}
class SpecificEvaluator3 : BaseEvaluator {
public:
SpecificEvaluator3(Info info): {};
virtual Result evaluate();
protected:
void helperMethod1(Info);
void helperMethod2(Info);
}
Or that
class Helper {
protected:
Helper(Whatever youneed);
void helperMethod1(Info);
void helperMethod2(Info);
}
class ArgSpecificEvaluator : public BaseEvaluator, protected Helper {
public:
ArgSpecificEvaluator (Arg arg) {};
Result evaluate() override; // Implementation Uses OtherInfo
}
class SpecificEvaluator3 : public BaseEvaluator , protected Helper {
public:
SpecificEvaluator3(Info info): {};
Result evaluate() override;
}
Note that i set ArgSpecificEvaluator
to also inherite the base BaseEvaluator
because it has the same evaluate
function.
In general, i try to go around the caveheat of inheritance by rather having an instance of a common class as a member rather than inheriting a class.
class Helper {
public:
Helper(Whatever youneed);
void helperMethod1(Info);
void helperMethod2(Info);
}
class ArgSpecificEvaluator : public BaseEvaluator {
public:
ArgSpecificEvaluator (Arg arg) {};
Result evaluate() override; // Implementation Uses OtherInfo
protected:
Helper helper;
}
class SpecificEvaluator3 : public BaseEvaluator {
public:
SpecificEvaluator3(Info info): {};
Result evaluate() override;
protected:
Helper helper;
}
I would imagine that using Arg
for all classes and having no-value or a default value in some cases is probably not a bad solution either.