I have a doubt about what would be the right OOP approach for implementing classes that do similar stuff with different parameters.
To provide a simple example, I would use two polynomial classes, please, don't give an answer specific to polynomials, e.g., saying that one could just create the generic class polynomial
, and let's pretend that there is no natural way to pass the coefficients c0
, c1
, c2
, ... as a list of variable length.
Let's say that I want several classes like polytwo
that represents second-degree polynomials, and polythree
that represents third-degree polynomials.
polytwo
has three variables, one for each coefficient (c0
, c1
, and c2
).
polythree
has four variables (c0
, c1
, c2
, and c3
).
Some methods are specific to the class, for example,
evaluate(x)
will return
c0 + c1*x + c2*x**2
forpolytwo
and
c0 + c1*x + c2*x**2 + c3*x**3
forpolythree
.Some methods will use the same code for both, for example
get_constant_coeff
will always returnc0
. Ordiscrete_integral_04
will return
evaluate(0) + evaluate(1) + evaluate(2) + evaluate(3)
The use for these classes is to provide several results when the underlying model changes, i.e., I am mostly interested to the results of the second kind of methods.
My first approach was to consider polythree
a child of polytwo
, since it does the same thing, but with the addition of a new variable, c3
. However this break the Liskov substitution principle when calling the initializer, since for polytwo
it would have three arguments, and for polythree
four.
On the other side, using a virtual poly
class, without an initializer (with only c0
as class variable) that implements get_contant_coeff
and discrete_integral_04
, will result in many lines of code being repeated. Specifically, both inizializers of polytwo
and polythree
will need to take c0
as an input and set the variable class c0 to it, and the copy constructors would look pretty much the same in both. Is this the right way to proceed?
An alternative I was considering was to initialize polythree
in the same way as polytwo
, but with the addition of a new method, set_c3
. But this way would make the code much more of a mess, since in place of
p = polythree(1,2,3,4)
I would now need
p = polythree(1,2,3)
p.set_c3(4)
and the more the additional parameters, the worse it gets (also, what if I forget some?)
Another alternative is a big class that takes many optional parameters, and if c3
is not set, it implements evaluate
in a different way. But what if evaluate
is much longer and much different for each class?
Also, are initializers with optional parameters a thing? Should I set c3
to null by default and then constantly check?
I expect that developers that will use just polytwo
will not want to bother about understanding what they should to do with this c3
that they don't even know what it does...
What I was wondering is whether there is a natural OOP way to face this kind of problem.
I'm working in python, but I don't think that the answer to this should be language specific.
set_c3
method that would be meaningless in the child class. See for example softwareengineering.stackexchange.com/questions/238176/…