На самом деле мы ошибались. Несмотря на то, что Java по умолчанию не позволяет переопределять статические методы, если вы тщательно изучаете документацию классов класса и метода в Java, вы все равно можете найти способ эмуляции статических методов, переопределяющих следующие методы:
import java.lang.reflect.InvocationTargetException;
import java.math.BigDecimal;
class RegularEmployee {
private BigDecimal salary = BigDecimal.ONE;
public void setSalary(BigDecimal salary) {
this.salary = salary;
}
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".02");
}
public BigDecimal calculateBonus() {
return salary.multiply(this.getBonusMultiplier());
}
public BigDecimal calculateOverridenBonus() {
try {
// System.out.println(this.getClass().getDeclaredMethod(
// "getBonusMultiplier").toString());
try {
return salary.multiply((BigDecimal) this.getClass()
.getDeclaredMethod("getBonusMultiplier").invoke(this));
} catch (IllegalAccessException e) {
e.printStackTrace();
} catch (IllegalArgumentException e) {
e.printStackTrace();
} catch (InvocationTargetException e) {
e.printStackTrace();
}
} catch (NoSuchMethodException e) {
e.printStackTrace();
} catch (SecurityException e) {
e.printStackTrace();
}
return null;
}
// ... presumably lots of other code ...
}
final class SpecialEmployee extends RegularEmployee {
public static BigDecimal getBonusMultiplier() {
return new BigDecimal(".03");
}
}
public class StaticTestCoolMain {
static public void main(String[] args) {
RegularEmployee Alan = new RegularEmployee();
System.out.println(Alan.calculateBonus());
System.out.println(Alan.calculateOverridenBonus());
SpecialEmployee Bob = new SpecialEmployee();
System.out.println(Bob.calculateBonus());
System.out.println(Bob.calculateOverridenBonus());
}
}
Результат:
0.02
0.02
0.02
0.03
, чего мы пытались достичь:)
Даже если мы объявим третью переменную Carl как RegularEmployee и назначим ей экземпляр SpecialEmployee, мы будем все еще имеют вызов метода RegularEmployee в первом случае и вызов метода SpecialEmployee во втором случае
RegularEmployee Carl = new SpecialEmployee();
System.out.println(Carl.calculateBonus());
System.out.println(Carl.calculateOverridenBonus());
просто посмотрите на консоль вывода:
0.02
0.03
;)
Если FooterComp находится под src, путь должен быть './FooterComp/Footer'
, а не '../FooterComp/Footer'
Редактировать
Index.js
[110 ]FirstComponent.js
render() {
const { module: Component } = this.state;
return (
<div className="App">
<header className="App-header">
<img src={logo} className="App-logo" alt="logo" />
<p>
Edit <code>src/App.js</code> and save to reload.
</p>
<a
className="App-link"
href="https://reactjs.org"
target="_blank"
rel="noopener noreferrer"
>
Learn React
</a>
</header>
{Component && <Component path= '../FooterComp/Footer' />}
</div>
);
}
Существует ограничение при использовании динамического импорта с «переменными частями», такими как import(`${path}`)
, поскольку ${path}
является переменной.
Во время создания пакета Webpack
В вашем случае, когда компонент import(`${path}`)
в Dynamic
назывался webpack, создавал пакет. Этот комплект был для FirstComponent
компонента. Внутри этого пакета веб-пакет содержит список компонентов, которые можно динамически импортировать с помощью «переменных частей» в компоненте FirstComponent
. Он содержал только файлы, которые находились в той же папке, где находился компонент FirstComponent
. Это потому, что вы использовали import(`${path}`)
в FirstComponent
.
Все это происходит потому, что webpack при компиляции не знает, какой будет точный путь импорта во время выполнения, так как вы используете динамический импорт с «переменными частями».
Во время запроса приложения React
Когда в компоненте Dynamic
было выполнено import(`${path}`)
. Пакет для FirstComponent
был запрошен. Как только пакет был получен, и он выполнил свой код, и path
, который вы указали в качестве компонента props
- FirstComponent
, не было в списке компонентов, которые можно динамически импортировать с помощью «переменных частей».
То же самое относится и к компоненту Dynamic
, если вы попытаетесь динамически импортировать файлы с «переменными частями» для файлов, которые находятся вне папки src
, вы получите ту же ошибку.
Итак, чтобы решить эту проблему, у вас есть пара опций
1) Поместите оба файла в одну папку
, т.е.
'src/Components/FirstComponent'
'src/Components/Footer'
И используйте
// In FirstComponent.js
componentDidMount() {
const { path } = this.props;
import(`${path}`)
.then(module => this.setState({ module: module.default }))
}
{Component && <Component path='./Footer' />} // Index.js
2) быть более точным, насколько это возможно
т.е.
// In FirstComponent.js
componentDidMount() {
const { path } = this.props;
import(`../FooterComp/${path}`)
.then(module => this.setState({ module: module.default }))
}
И использовать
{Component && <Component path='Footer' />} // In index.js
ОБНОВЛЕНИЕ
Пакет, созданный веб-пакетом для componentDidMount:
1) для динамического импорта с переменными, но более конкретным способом, например import(`../FooterComp/${path}`)
_createClass(App, [{
key: "componentDidMount",
value: function componentDidMount() {
var _this2 = this;
var path = this.props.path;
// "import(`../FooterComp/${path}`)" is converted to code below
__webpack_require__(/*! ../FooterComp */ "./src/FooterComp lazy recursive ^\\.\\/.*$")("./" + path)
.then(function (module) {
return _this2.setState({ module: module.default });
});
Код для [ 1126] в связке
/***/ "./src/FooterComp lazy recursive ^\\.\\/.*$":
/*!**************************************!*\
!*** ./src/FooterComp lazy ^\.\/.*$ ***!
\**************************************/
/*! dynamic exports provided */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {
var map = {
"./Footer": [
"./src/FooterComp/Footer.jsx",
0
],
"./Footer.jsx": [
"./src/FooterComp/Footer.jsx",
0
]
};
function webpackAsyncContext(req) {
var ids = map[req];
if(!ids)
// Code throwing "ERROR"
return Promise.reject(new Error("Cannot find module '" + req + "'."));
return __webpack_require__.e(ids[1]).then(function() {
return __webpack_require__(ids[0]);
});
};
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
return Object.keys(map);
};
webpackAsyncContext.id = "./src/FooterComp lazy recursive ^\\.\\/.*$";
module.exports = webpackAsyncContext;
/***/ })
2) для динамического импорта с переменными, т.е. import(`${path}`)
_createClass(App, [{
key: "componentDidMount",
value: function componentDidMount() {
var _this2 = this;
var path = this.props.path;
// "import(`${path}`)" is converted to code below
__webpack_require__(/*! . */ "./src/Components lazy recursive ^.*$")("" + path).then(function (module) {
return _this2.setState({ module: module.default });
});
Код для ./src/Components lazy recursive ^.*$
/***/ "./src/Components lazy recursive ^.*$":
/*!**********************************!*\
!*** ./src/Components lazy ^.*$ ***!
\**********************************/
/*! dynamic exports provided */
/*! all exports used */
/***/ (function(module, exports, __webpack_require__) {
var map = {
"./FirstComponent": [
"./src/Components/FirstComponent.jsx"
],
"./FirstComponent.jsx": [
"./src/Components/FirstComponent.jsx"
]
};
function webpackAsyncContext(req) {
var ids = map[req];
if(!ids)
// Code throwing "ERROR"
return Promise.reject(new Error("Cannot find module '" + req + "'."));
return Promise.all(ids.slice(1).map(__webpack_require__.e)).then(function() {
return __webpack_require__(ids[0]);
});
};
webpackAsyncContext.keys = function webpackAsyncContextKeys() {
return Object.keys(map);
};
webpackAsyncContext.id = "./src/Components lazy recursive ^.*$";
module.exports = webpackAsyncContext;
/***/ }),