问题
I have a class, which depends on type of string, gets in in a swithc statement, and call to de new "class_name" related (constructor).
But, I would like to know if there is a better way to solve this.
It would be ideal if there is a way to call the builder independently, within a specific folder, of all the classes that exist.
Project example:
- Types/_String.js
- Types/_Date.js
- Types/_Integer.js
- .....
- TypeSwitcher.js (contains the switch that calls the constructors of the "Types" classes).
Associated Code to "TypeSwitcher.js":
"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";
import Document from "./Inputs/Document";
import Container from "./Inputs/Container";
export default class InputFactory
{
static getInput(key,typedObject,form,inputDef)
{
let type=typedObject.getField(key).getTypeName();
switch (type)
{
case "String": {
return new _String(key,typedObject,form,inputDef);
} break;
case "Integer": {
return new _Integer(key,typedObject,form,inputDef);
} break;
case "Date": {
return new _Date(key,typedObject,form,inputDef);
}break;
case "Document": {
return new Document(key,typedObject,form,inputDef);
}break;
case "Container": {
return new Container(key,typedObject,form,inputDef);
}break;
default: {throw "Input undefined:"+type}
}
}
}
New (edited) I don't have classes only with an underscore "_", also normal. And I have put indent script since I am redefining the basic types of the system to customize them to my need (String.js is reserved and does not leave, so _String.js)
I tried to do something like that:
"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";
const predefinedSystemVar = ["String", "Integer", "Date"];
export default class InputFactory
{
static getInput (key, typedObject, form, inputDef)
{
let type = typedObject.getField(key).getTypeName();
if (predefinedSystemVar.includes(type) )
type = `_${type}`;
return eval( `new types[type](key, typedObject, form, inputDef)` );
}
}
Updated But it didnot work well, because of webpack. v4 :( I think webpack v4 changes names to imports, etc., and it does not work the code trick ...
Problem, if I create a new class in the future, I would have to add a new "case" and import to contemplate the new constructor.
So, the solution I tried, I dont like so much, because I'd have to add new variables to "predefinedSystemVar"...
Is there something in ES6 or javascript to get this work in a better and optimized way instead of switch -> case?
Additional note: Project enviroment:
- Webpack v.4.x
- Babel 7.x
- ES6
package.json
{
"devDependencies": {
"@babel/cli": "^7.7.0",
"@babel/core": "^7.7.2",
"@babel/plugin-proposal-class-properties": "^7.7.0",
"@babel/preset-env": "^7.7.1",
"babel-loader": "^8.0.6",
"cypress": "^3.7.0",
"webpack": "^4.41.2",
"webpack-cli": "^3.3.10",
"webpack-dev-server": "^3.9.0"
},
回答1:
Yes, if I am understanding this correctly it should be possible. The below code should work, unless I made some syntactical error. It does require the updating of a classes array, but is less work than updating the switch case and the other solution. I hope this helps and if it does please mark as the answer, have a good rest of your day, cheers!
"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";
const classes = {
_String,
_Integer,
_Date
};
export default class InputFactory
{
static getInput(key,typedObject,form,inputDef)
{
let type=typedObject.getField(key).getTypeName();
if (classes["_"+type]{
return new classes["_"+type](key,typedObject,form,inputDef);
} else {
throw "Input undefined:"+type
}
}
}
回答2:
A way is create an object which keys are the same as cases and values are a function that returns a value as you desire as below:
"use strict"
import _String from "./Inputs/_String";
import _Integer from "./Inputs/_Integer";
import _Date from "./Inputs/_Date";
export default class InputFactory {
static getInput(key, typedObject, form, inputDef) {
let type = typedObject.getField(key).getTypeName();
const operations = {
"String": () => new _String(key, typedObject, form, inputDef),
"Integer": () => new _Integer(key, typedObject, form, inputDef),
"Date": () => new _Date(key, typedObject, form, inputDef),
}
try {
return operations[type]();
} catch() {
throw "Input undefined:" + type
}
}
}
来源:https://stackoverflow.com/questions/59454558/better-way-to-call-new-constructor-classes-not-using-a-switch-in-javascript-es6