Reputation: 315
Sorry if this is bizarre or anti-pattern.
Suppose I have a static method on a child class, e.g (heavily simplified for readability)
class User extends Model {
//...
static getAll(){
db.execute('SELECT * FROM users');
}
}
Since I have multiple models I might want a getAll
method on, it seems ideal to define getAll
on the Model
class, which makes reference to a tableName
class variable. Ideally it would look something like
class Model {
static getAll(){
db.execute(`SELECT * FROM ${this.tableName}`);
}
}
//...
User.tableName = 'users';
This won't work, because ES6 doesn't like you defining class variables like that. There are a number of workarounds, such as adding a tableName
parameter in the parent then applying users
to it in User
:
class Model {
static getAll(tableName) {
db.execute(`SELECT * FROM ${tableName}`)
}
}
//...
class User extends Model{
static getAll() {
Model.getAll('users')
}
}
but explicitly re-writing inherited functions for all of a class's children like this seems dreadfully anti-pattern. Other solutions I've seen (such as using static functions to return constants, or wrapping both classes in an object) are kinda ugly and not a pattern I want to commit to unless I have to. So I'm looking for an easily-readable ES6 pattern that lets me do the following:
Does such a solution exist, or is it worth doing it the 'hard way' in ES5?
Upvotes: 3
Views: 2008
Reputation: 955
A simplification of the good solution of @Christian Santos
class Model {
static getAll() {
console.log(this.tableName); // will refer to child's static var
}
static randomFunc() {
console.log(this.tableName); // will also refer to child's static var
}
}
class User extends Model {
static tableName = "users";
}
class Worker extends Model {
static tableName = "workers";
}
User.getAll(); // prints users
User.randomFunc(); // prints users
Worker.getAll(); // prints workers
Worker.randomFunc(); // prints workers
Upvotes: 0
Reputation: 817138
This won't work, because ES6 doesn't like you defining class variables like that.
What makes you think that? User
is a function like any other function. Static methods become properties of that function. Assigning a property directly to User
works just fine.
class Model {
static getAll() {
return `SELECT * FROM ${this.tableName}`;
}
}
class User extends Model {}
User.tableName = 'users';
class Product extends Model {}
Product.tableName = 'product';
console.log(User.getAll());
console.log(Product.getAll());
Upvotes: 2
Reputation: 5456
Although this feels slightly hackish -- there is a way to achieve what you need using these two facts about ES6 classes:
static get
in the class definition -- and these getters will function as static properties. this
to call other static methods. This means your parent class's static method can use this
to refer to a static method in your child class. Altogether, the code would look like this:
class Model {
static getAll() {
console.log(this.tableName); // will refer to child's static getter
}
static randomFunc() {
console.log(this.tableName); // will also refer to child's static getter
}
}
class User extends Model {
static get tableName() {
return "users"; // define child's tableName here
}
}
class Worker extends Model {
static get tableName() {
return "workers"; // define child's tableName here
}
}
User.getAll(); // prints users
User.randomFunc(); // prints users
Worker.getAll(); // prints workers
Worker.randomFunc(); // prints workers
Upvotes: 1