Reputation: 1263
I have to work with many components of a third party library that all extend an abstract class which behavior I have to alter. To make it more clear, see the following lines of sample code:
abstract class ThirdPartyParentClass {
parentMethod() {
// I need to alter this method...
}
}
class ThirdPartyComponent1 extends ThirdPartyParentClass {
componentMethod() {
parentMethod(); // ...because it gets called here...
}
}
class ThirdPartyComponent2 extends ThirdPartyParentClass {
componentMethod() {
parentMethod(); // ...and here...
}
}
// ...and in a few other places.
One obvious solution would be to extend the parent class, overwrite the respective method, and duplicate the code of all its components, making them extend my custom parent class instead. However, since the third party library is currently under heavy development, I fear that I would introduce a lot of technical debt by doing so.
Is there another possibility to reach this goal?
Upvotes: 2
Views: 2798
Reputation: 46
Assuming the parent or the child classes are injectables you should be able to use class providers: https://angular.io/guide/dependency-injection-providers#aliased-class-providers
When the parent class is an injectable and injected via the constructor in other 3rd party classes you can extend the parent class, overwrite the method and then configure your module to use your class instead of the 3 party parent class.
When the 3rd party child classes are injectables you have to extend all child classes and overwrite the parent method. After that you configure your module.
Upvotes: 0
Reputation: 1481
I think this is a good use case for composition
Create your own class and create your custom method :
export class MyCustomImplementation {
parentMethod() {
// this is the parentMethod altered
}
}
Create and export a function to apply the mixin to your class :
export function applyMixins(derived: any, bases: any[]) {
bases.forEach((base) => {
Object.getOwnPropertyNames(base.prototype)
.filter((propertyName) => propertyName.toLowerCase() !== 'constructor')
.forEach((propertyName) => {
derived.prototype[propertyName] = base.prototype[propertyName];
});
});
}
In your ThirdPartyComponent, import and implements your class :
class ThirdPartyComponent1 extends ThirdPartyParentClass, implements MyCustonImplementation {
constructor() {
super();
applyMixins(ThirdPartyComponent1, [MyCustomImplementation]);
}
componentMethod() {
parentMethod(); // ...because it gets called here...
}
}
That way, you do not change the tight-coupled inheritance relation between ThirdPartyComponents and ThirdPartyClass, but you can overwrite the method.
I made a dummy stackblitz implementation
Upvotes: 2