Let's say I have a Thing
class which I want to be both Hideable
and Openable
.
Using a similar approach to Douglas Crockford's object creation through composition, I have been able to "inherit" from multiple classes.
This approach does not work with accessors (getter/setters).
I need to use classes as it's a requirement. I'm also finding that I am duplicating functionality from class to class, but I don't want these to inherit from a base class.
Any ideas?
The progress I have made so far is in the below snippet:
class Openable {
constructor(isOpen = false) {
this._isOpen = isOpen;
}
get isOpen() {
return this._isOpen + ' is stupid.';
}
set isOpen(value) {
this._isOpen = value;
}
}
class Hideable {
constructor(isHidden = false) {
this._isHidden = isHidden;
}
get isHidden() {
return this._isHidden + ' is stupid.';
}
set isHidden(value) {
this._isHidden = value;
}
}
class Thing {
constructor(config) {
let { isOpen, isHidden } = config;
let openable = new Openable(isOpen);
this.isOpen = openable.isOpen;
let hideable = new Hideable(isHidden);
this.isHidden = openable.isHidden;
}
}
let thing = new Thing({
isOpen: true,
isHidden: false
});
Because isOpen
and isHidden
are accessors, you can't just grab a copy of them, you have to access them when you want them.
Still, you can create your own isOpen
, isHidden
which use the underlying ones:
let openable = new Openable(isOpen);
Object.defineProperty(this, "isOpen", {
get: () => openable.isOpen,
set: value => {
openable.isOpen = value;
}
});
let hideable = new Hideable(isHidden);
Object.defineProperty(this, "isHidden", {
get: () => hideable.isHidden,
set: value => {
hideable.isHidden = value;
}
});
Naturally, if you do this a lot, you'd want to have a worker function to set that up rather than retyping it all the time:
function wrapProperty(dest, src, name) {
Object.defineProperty(dest, name, {
get: () => src[name],
set: value => { src[name] = value; }
});
}
(or do it by grabbing the property descriptor and updating it)
then:
wrapProperty(this, openable, "isOpen");
wrapProperty(this, hideable, "isHidden");
I'd question the requirement that you must use class
for Openable
and Hideable
. They look much more like mixins to me.