I have a main class named Rule
with a param
attribute and several subclasses as example:
class Rule {
param = {}
constructor (param) {
// here I want to add the logic to fuse this.param from child component (all are different) and param provided to the constructor
}
}
class SubRule1 extends Rule {
param = {
subparam: {
values: ['A', 'B', 'C'],
value: 'A'
}
}
constructor (param) {
super(param)
}
}
class SubRule2 extends Rule {
param = {
subparam: {
values: [1, 2],
value: 1
}
}
constructor (param) {
super(param)
}
}
let myrule = new SubRule1({ subparam: 'B' })
>> expected Object { subparam: { values: ['A', 'B', 'C'], value: 'B' }}
let myrule2 = new SubRule2({ subparam: 2 })
>> expected Object { subparam: { values: [1, 2], value: 2 }}
When instantiate a new object, I would like to fuse this.param
and the param
parameter given to the constructor
for all the subclasses. I wanted to add the logic in the Rule
class, however, when accessing this.param
in the Rule.constructor
class I do not access the child this.param
attribute but the one defined in Rule
.
What would be the right design to properly initiate this.param
in all subclasses ?
3
Answers
To access the param parameter from parent class constructor, you should not use
this.param
, instead just useconsole.log(param)
which is passed as parameter to the contructor of parent class.this.param
is a pointer to the variable of that class only.Something like this may work for you.
The pattern you’re looking for is
To make this work with inheritance,
defaults
must be static:If you want to merge them deeply, this is another, more complicated story.
From my above comments …
(1) First things first … regarding the code comment of the OP’s
Rule
constructor …… a parent- or super-class has to be oblivious (thus it does not make any assumptions) about child / sub-class properties and operations.
(2) In addition, regarding just the handling of each of the Sub/Rules
param
member handling, no inheritance, hence noRule
–SubRule
(parent-child) relationship is even needed. This is due to how at construction time the initialization of each instance’sthis.param
gets handled.Even though as with the OP’s example code both (sub-)types
SubRule1
andSubRule2
each extend the (super-)typeRule
thethis.param
initialization is covered/shadowed entirely by each of the types itself. Whatever valuethis.param
was, at the end of a super call (chain), at the latest with any sub-type constructor this value gets entirely reassigned/overwritten (like demonstrated with the OP’sparams
defaults ofSubRule1
andSubRule2
). Thus, if it was not for any other prototypal functionality which hasn’t been shown yet, anyRule
related inheritance is totally unnecessary.(3) Moreover, the OP with one of the more recent edits introduced a far more complex merge behavior for
param
objects than one could have easily achieved with non nested objects and just e.g. …Instead the expected merger of …
… and of …
… is …
… which asks for a custom merge implementation.
Summary The OP’s main task is rather implementing a suitable custom merge strategy than making use of sub-class/type based inheritance since there most probably might not even be a valid reason for the latter.
The next provided example code proves the above said (though it keeps the inheritance feature, in order to stay with the OP’s main code structure).
Edit
In case the OP wants to go for full inheritance with parameter passing/forwarding via
super
calls, the approach needs to be changed from defining each type’s defaultparam
as own property.This is due to
this
(hencethis.param
) is not allowed to be accessed before or during asuper
call. Thus each type’s defaultparam
configuration has to be stored as e.g. local variable within each type’s (or all type’s) module scope. I would not declare such configurations as static class properties for they are exposed then, whereas a module scope ensures the protection of each defaultparam
config.The before provided above example code which actually does not need any inheritance would change then to a real inheritance approach where the implementation might be similar to the next provided code …
Edit due to a user’s comment …
One also could make use of the
_.merge
and_.cloneDeep
methods of either libraries Lodash or Underscore.js.