I am currently trying to figure out a way to assign methods to the super object in a class, in order to extend a functionality inside a class.
I want to create a "Component" class and have each class that extends the "Component" class have different methods depending on the component needs. I want to use the term "describe" for the method that would extend the super object. Therefore, I am describing the component.
Here is an example:
class Component {
constructor (args) {
this.template = args.template;
}
getTemplate () {
return this.template;
}
describe () {
//The magic should happen here
}
}
Class Controller describer
class Controller {
constructor () {
}
getEvents () {
return {};
}
}
Extending the Component class.
Then, using the "describe" method to inject other methods from other classes.
class example extends Component {
constructor () {
super({template: '<div></div>'});
super.describe({
Controller
});
super.getTemplate();
super.getEvents();
}
}
var app = new App({
example
});
Is it possible? Thank you :)
Related
This is something that if I'm able to achieve will be able to design a very easily extendible decorator factory for a project I'm working on.
Basically, I want to be able to use a super class's methods as a decorator for the sub-classes property.
This is usually how decorators work:
import { handleSavePropertyNameDecorator } from "./W-ODecorator"
class Main {
#handleSavePropertyNameDecorator
test1: string = ""
}
export default Main
And then the decorator function:
const propertyNames = [];
export const handleSavePropertyNameDecorator = (_instance: any, propertyName: string) => {
console.log("Executing handleSavePropertyNameDecorator")
propertyNames.push(propertyName);
}
However, instead of defining a separate function for the decorator, I'd like the decorator function to come from the super class:
import SuperClass from "./SuperClass"
class Main extends SuperClass{
#this.handleDecoratorFunction
test1: string = ""
}
export default Main
class SuperClass {
static propertyNameArray: string[] = [];
protected handleDecoratorFunction(_instance: any, propertyName: string) {
console.log("executing handle decorator function from super class!")
SuperClass.propertyNameArray.push(propertyName);
}
}
export default SuperClass;
Currently the keyword "this" has a compilation error that states it's possibly undefined. I've run this code and it doesn't execute the decorator function.
My question is this approach possible with some type of workaround? If this is possible that will significantly improve my organization.
Thank you in advance!
No, you can't do that, the decorator is applied when the class is defined not when it's instantiated. There are no instance methods from your superclass available.
However, you can do this with a static method of course:
class SuperClass {
static propertyNameArray: string[] = [];
protected static handleDecoratorFunction(_instance: any, propertyName: string) {
console.log("executing handle decorator function from super class!")
this.propertyNameArray.push(propertyName);
}
}
class Main extends SuperClass{
#SuperClass.handleDecoratorFunction
test1: string = ""
}
export default Main
In a library that I wish to extend without modifying its code, several classes inherit from the same imported one. That is in this BaseClass I would need to overwrite a specific method.
In the library (written in TypeScript) :
import { BaseClass } from './base_class';
export class ClassA extends BaseClass {}
import { BaseClass } from './base_class';
export class ClassB extends BaseClass {}
…
In the external extension I wish to write :
import { BaseClass } from 'library';
export class ExtendedBaseClass extends BaseClass {
oneMethod() {
const data = BaseClass.prototype.oneMethod.call(this);
// make additional things with data
return data;
}
}
Is there a way for this new ExtendedBaseClass to become the parent of all ClassXs ? At least in a new extended and re-exported version of them without the need to copy their internal code.
Is there a way for this new ExtendedBaseClass to become the parent of all ClassXs?
No.
An alternative might be to replace the one method directly on the base class:
import { BaseClass } from 'library';
const oneMethod = BaseClass.prototype.oneMethod;
Object.defineProperty(BaseClass.prototype, 'oneMethod', {
value() {
const data = oneMethod.call(this);
// make additional things with data
return data;
},
});
There's no way to do exactly what you're asking, but you could achieve the same result by extending each class individually.
ExtendedClassA extends ClassA {
oneMethod() {
// call a shared method if you need to reuse
}
}
// ExtendedClassB, etc
This is my main class (it uses a subclass:)
import SubClass from './SubClass'
class MainClass extends classes(SubClass) {
constructor () {
// some code
}
}
window.MainClass = new MainClass()
export default MainClass
This is the subclass:
class SubClass {
constructor () {
this.someMethod = function () {
// some code
}
}
}
export default SubClass
If I want to use a method from the SubClass I can write: MainClass.someMethod.
How to modify this code so I write: MainClass.SubClass.someMethod instead?
So I can write:
MainClass.SubClass.someMethod
MainClass.SubClass2.someMethod
In case I need another SubClass?
I think you need to call super(). And classes() seem doen't need to be added.
When used in a constructor, the super keyword appears alone and must be used before the this keyword is used.
See document
import SubClass from './SubClass'
class MainClass extends SubClass {
constructor () {
super();
console.log(this.someMethod)
}
}
Hope this help
I need to extend the two classes from the same namespace.
for ex:
declare namespace myNameSpace{
class class1{
///some methods will be here
}
class class3 extends class1{
//some method wil be here
}
class class2 extends myNameSpace. class3 {
//some methods will be here
}
export namespace class2 {
//declaration will be here
}
}
i need to extend the 'myNameSpace.class1' class as well as 'class2' namespace.
class newClass extends myNameSpace.class1, myNameSpace.class2 {
constructor() {
super();
}
}
If i call the both the classes, i got an error message
classes can only extend a single class
Is there any other way to fix this issue in typescript.
Is there any other way to fix this issue in typescript.
TypeScript is single inheritance by design.
You can use mixins but you can't override methods (unless you write a custom applyMixins methods)
Using the method:
function applyMixins(derivedCtor: any, baseCtors: any[]) {
baseCtors.forEach(baseCtor => {
Object.getOwnPropertyNames(baseCtor.prototype).forEach(name => {
derivedCtor.prototype[name] = baseCtor.prototype[name];
});
});
}
You have to implement (on empty way)
class NewClass implements myNameSpace.class1, myNameSpace.class2 {
// empty implementation
public methodFrom1 : ()=>void;
public methodFrom2 : ()=>number;
constructor() {
// no super()
}
}
now use mixing to actually make it multi extend classes:
applyMixins(NewClass, [myNameSpace.class1, myNameSpace.class2]);
and now you can create the class
const foo = new NewClass()
foo.methodFrom1() // actually calls nameSpace.class1.prototype.methodFrom1
I'm extending a base class and overriding a method in the base class. But when I call it, it calls the super class version. How do I override the method?
var Hello = React.createClass( {
getName: function() { return "super" },
render: function() {
return <div>This is: {this.getName()}</div>;
}
});
class HelloChild extends Hello {
constructor(props) {
super(props);
console.log( this.getName());
}
getName()
{
return "Child";
}
};
I want it to print "This is: Child" but it prints "This is: super"
The problem is that you're mixing ES6 type class declaration (ex. Hello) with old school Javascript declaration (ex. HelloChild). To fix HelloChild, bind the method to the class.
class HelloChild extends Hello {
constructor(props) {
super(props);
this.getName = this.getName.bind(this); // This is important
console.log( this.getName());
}
getName()
{
return "Child";
}
};
Then it'll work.
I found the answer (adapted from here: https://gist.github.com/Zodiase/af44115098b20d69c531 ) - the base class needs to also be defined in an ES6 manner:
class Hello extends React.Component {
//abstract getName()
getName()
{
if (new.target === Hello) {
throw new TypeError("method not implemented");
}
}
render() {
return <div>This is: {this.getName()}</div>;
}
};
Actually you can override method to execute code from your subclass
class Hello extends React.Component {
getName() {
super.getName();
}
}
class HelloChild extends Hello {
getName()
{
return "Child";
}
}
Please note that this answer proposes different approach:
I wonder why you should do this in the first place, my point is that directly coupling two react components is not a right way to implement re-usability in React.
If you are trying to have multiple child components which extends one parent, What I would do is, to have child components and a higher-order component and then implement common functionality with Composition. This way you can skip those methods, which you were trying to override and so everything would stay clear.