Say we want to be able to call functions run
of ImplementationA
and ImplementationB
polymorphically (dynamically at runtime) in this example:
struct Input {};
struct MoreInputA {};
struct ImplementationA {
void run(Input input, MoreInputA more_input);
};
struct MoreInputB {};
struct ImplementationB {
void run(Input input, MoreInputB more_input);
};
Both take some Input
in the same format, but some MoreInput
in different formats. ImplementationA
and ImplementationB
can only do their job on their specific MoreInputA
and MoreInputB
respectively, i.e. those input formats are fixed. But say MoreInputA/B
can be converted from a general MoreInput
. Then a simple polymorphic version could look like this:
struct Input {};
struct MoreInput {};
struct ImplementationBase {
virtual void run(Input input, MoreInput more_input) = 0;
};
struct MoreInputA {};
MoreInputA convertToA(MoreInput);
struct ImplementationA : public ImplementationBase {
void run(Input input, MoreInputA more_input);
void run(Input input, MoreInput more_input) override {
run(input, convertToA(more_input));
}
};
// same for B
However, now the more_input
has to be converted in every call to run
. A lot of unnecessary conversions are forced on a user of the polymorphic interface if they want to call run
repeatedly with varying input
but always the same more_input
. To avoid this, one could store the converted MoreInput
inside of the objects:
struct Input {};
struct MoreInput {};
struct ImplementationBase {
virtual void setMoreInput(MoreInput) = 0;
virtual void run(Input input) = 0;
};
struct MoreInputA {};
MoreInputA convertToA(MoreInput);
struct ImplementationA : public ImplementationBase {
void run(Input input, MoreInputA more_input);
MoreInputA more_input_a;
void setMoreInput(MoreInput more_input) override {
more_input_a = convertToA(more_input);
}
void run(Input input) override {
run(input, more_input_a);
}
};
// same for B
Now it is possible to do the conversion only when the user actually has new MoreInput
. But on the other hand, the interface is arguably more difficult to use now. MoreInput
is not a simple input parameter of the function anymore, but has become some sort of hidden state of the objects, which the user has to be aware of.
Is there a better solution that allows avoiding conversion when possible but also keeps the interface simple?
Aucun commentaire:
Enregistrer un commentaire