Javascript 项目之间的类继承
我正在管理一个小产品线的UI。所有这些产品都是或多或少具有相同模块的硬件,但作为一个单元本身,可能具有额外的全局功能。这些全局功能与这些模块交互,通常为多个模块提供相同的功能。我正努力用逻辑类继承来维护OOP方法,但有时似乎不可能不复制粘贴某些功能 在本例中,我用Javascript 项目之间的类继承,javascript,oop,Javascript,Oop,我正在管理一个小产品线的UI。所有这些产品都是或多或少具有相同模块的硬件,但作为一个单元本身,可能具有额外的全局功能。这些全局功能与这些模块交互,通常为多个模块提供相同的功能。我正努力用逻辑类继承来维护OOP方法,但有时似乎不可能不复制粘贴某些功能 在本例中,我用LightSwitch说明了该情况。产品A和产品B都可以有一个灯开关产品B也有一个报警开关产品B的光开关和报警开关的实现也需要一个功能完全相同的定时器产品A不支持计时器 我在这里看到的唯一解决方案是跨模块复制粘贴。我想不出任何其他方法可
LightSwitch
说明了该情况。产品A和产品B都可以有一个灯开关
产品B也有一个报警开关
产品B的光开关和报警开关的实现也需要一个功能完全相同的定时器产品A不支持计时器
我在这里看到的唯一解决方案是跨模块复制粘贴。我想不出任何其他方法可以在不破坏模型的情况下扩展它
// Common components
class Switch {
constructor() {
this.state = false;
}
open() {
this.state = true;
}
close() {
this.state = false;
}
}
class LightSwitch extends Switch {
constructor() {
super();
this.colour = "white";
}
changeColour(colour) {
this.colour = colour;
}
}
// Product A
class LedSwitch extends LightSwitch {
constructor() {
super();
this.blink = false;
}
blink(state) {
this.blink = state;
}
}
// Product B
// AlarmSwitch and ProductBLightSwitch both need a "timer"
class AlarmSwitch extends Switch {
constructor() {
super();
this.sound = "alarm.wav";
this.timer = 5000;
}
changeSound(sound) {
this.sound = sound;
}
resetTimer() {
this.timer = 0;
}
}
class ProductBLightSwitch extends LightSwitch {
costructor() {
super();
this.timer = 5000;
}
resetTimer() {
this.timer = 0;
}
}
可以考虑将“代码>//公共组件< /代码>重构和分解为(i)基于行为的混合/特征,并将(ii)类型的外壳类只负责类型签名,并将已经存在的代码粘贴在一起(通过组合和继承进行代码重用)。同时,人们可能更关心如何访问/隐藏对象的当前状态。这样一种方法将在下面的OP的重构示例代码中演示
//通用组件
变量
withSerializableTypeProxy=(函数(){
函数到字符串(类型){
返回JSON.stringify(type);
}
函数值(类型){
返回JSON.parse(JSON.stringify(type))
}
设defineProperty=Object.defineProperty;
返回函数特性(stateValue){
常数
复合类型=此;
defineProperty(复合类型,'toString'{
值:(()=>toString(stateValue))
});
定义属性(复合类型,'valueOf'{
值:(()=>valueOf(stateValue))
});
};
}());
带有ChangeableColorProxy(stateValue)的函数{
常数
复合类型=此;
compositeType.changeColor=((colorValue)=>stateValue.color=colorValue);
Object.defineProperty(复合类型,'color'{
可枚举:正确,
获取:(()=>stateValue.color)
});
stateValue.color='white';//设置默认值。
}
类开关{
构造函数(stateValue){
stateValue=((stateValue!=null)和&(typeof stateValue=='object')&&stateValue)|{};
stateValue.isOpen=true;
常数
开关类型=此;
调用(switchType、stateValue);
switchType.open=(()=>stateValue.isOpen=true);
switchType.close=(()=>stateValue.isOpen=false);
Object.defineProperty(此“等参线”{
可枚举:正确,
获取:(()=>stateValue.isOpen)
});
}
}
类光开关扩展开关{
构造函数(stateValue){
stateValue=((stateValue!=null)和&(typeof stateValue=='object')&&stateValue)|{};
超级(状态值);
withChangeableColorProxy.call(this,stateValue);
}
}
变量
lightSwitch=(新的lightSwitch);
控制台日志(“lightSwitch:,lightSwitch”);
log(((lightSwitch的lightSwitch实例)?,(lightSwitch的lightSwitch实例));
log(((lightSwitch instanceof Switch)?,(lightSwitch instanceof Switch));
log(((lightSwitch+“”):“,(lightSwitch+“”));
log(“lightSwitch.toString():”,lightSwitch.toString());
log(“lightSwitch.valueOf():”,lightSwitch.valueOf());
log(“Object.keys(lightSwitch):”,Object.keys(lightSwitch));
log(“lightSwitch.isOpen:”,lightSwitch.isOpen);
log(“lightSwitch.close():”,lightSwitch.close());
log(“lightSwitch.isOpen:”,lightSwitch.isOpen);
log(“lightSwitch.open():”,lightSwitch.open());
log(“lightSwitch.isOpen:”,lightSwitch.isOpen);
log(“lightSwitch.color:,lightSwitch.color”);
log(“lightSwitch.changeColor('pink'):”,lightSwitch.changeColor('pink'));
log(“lightSwitch.color:,lightSwitch.color”);
log(“lightSwitch.changeColor('light-blue'):”,lightSwitch.changeColor('light-blue'));
log(“lightSwitch.color:,lightSwitch.color”)代码>
。作为控制台包装器{max height:100%!important;top:0;}
不要被迫将所有内容都转换为一个范例。使用您可以使用的任何语言特性来编写自然的解决方案。也许是一种组合方法,您可以在其中创建一个单独的计时器
对象,该对象提供通用计时器功能,如reset()
,并在计时器关闭时接收一个回调函数,用于任何需要的特定功能。然后,任何需要计时器的类都可以有自己的计时器实例。我建议您搜索偏好组合而不是继承。有些情况下使用继承,有些情况下使用组合。我知道你正在经历一个“遗产地狱”的案子。你可以试着自然地思考问题。如果你认为Y是X是不自然的,那么也许你可以从Y的角度考虑更多,和X.有关系,即使你在你的问题中使用“某物有其他东西”,而“某物是其他东西”。也许AlarmSwitch是一个LightSwitch,但也许ProdA不是一个LightSwitch,而是一个LightSwitch。当有意义的时候,我会把东西移动到子组件中。在这种情况下,定时器
就是一个很好的例子。计时器可以独立存在。但就其本身而言,它什么也不做。在这种情况下,它需要连接到报警开关
和报警开关
。问题是,对于这两个类,它以完全相同的方式连接起来……我绝对不会使用inher