Javascript 中的多重继承与原型链
Multiple inheritance in Javascript with prototype chain
我有一个 JavaScript MVC 设计,使用原型实现,其中不同的项目可以根据控制器的决定以不同的方式显示。例如,一个 'Event' 项目可能会与视图 ViewTabs
或 ViewSimple
一起显示。 Class 层级:
ViewBase
- ViewTabs
-- EventViewTabs, which implements EventViewTabs.Validate
- ViewSimple
-- EventViewSimple, which implements EventViewSimple.Validate
决定是使用 EventViewTabs
还是 EventViewSimple
是由 EventController
完成的。我的问题是:我有一个 Validate
方法来检查来自 Event
视图的输入,但是这个方法对于 EventViewTabs
和 EventViewSimple
视图是相同的。我应该把 Validate
放在哪里以避免重复?我不能把它放在 ViewBase
中,因为其他项(例如 User
)也继承自此 class。
看来我需要多重继承,但有更聪明的方法吗?我有一种感觉,我忽略了一些明显的东西。
一种方法是使用 mixin 添加其他行为(这是 ruby 方法,react.js 和 react.rb 也使用这种方法)您可以 google 对于 javascript+mixins 并找到一些像这样的优秀教程:http://raganwald.com/2014/04/10/mixins-forwarding-delegation.html
对于您的具体情况,validate
(或者可能 validator
)将是 mixin。
为什么不做这样的事情:
ViewBase
ViewBase
-EventValidator, which implements Validate
--ViewTabs
---EventViewTabs
--ViewSimple
---EventViewSimple.
还考虑使用组合而不是继承,请参阅this video
您缺少作文。继承并不能解决有关代码重用的所有问题,以避免 copy-paste 编程.
假设您有一个 View
基本原型:
function View() { }
如果想让这个视图支持校验,可以在构造函数中注入校验依赖:
function View(validator) {
this.validator = validator;
}
View.prototype = {}; // A lot of functions here
也就是说,现在任何继承 View
原型的视图都将有一个关联的验证器。换句话说:你不需要在你的具体视图中派生两个原型(你不需要也做不到)。
另一方面,就 object-oriented 编程而言,从 Validator
派生以创建 View
是没有意义的。
当你说 视图有验证器 时,因为你使用 has 作为动词,所以你在谈论关联(组合的一种形式)。或者,当您说 我的主屏幕 是 作为视图 时,我们在谈论 继承 , 因为一个特定的视图必须也是一个视图,所以它需要基础视图的成员像一个视图一样。
基本上,您的验证器可以 tailor-made 具有它必须使用的类型。在 UML 中,它被称为组合。我计算出你的代码如下:
function Validator {}
Validator.prototype.validate = function(arg) {
//arg is no longer inputs
return true|false; //the ultimate output along with additional information;
}
function EventViewTabsValidator() {}
EventViewTabsValidator.prototype = Object.extend(Validator.prototype); //inheritance
EventViewTabsValidator.prototype.constructor = EventViewTabsValidator; //enforce the constructor to point to your derived type
EventViewTabsValidator.prototype.validate = function() {
var inputs = $('inputs');
var param = 'do some stuff specific to EventViewTabsValidator based on the inputs';
return Validator.prototype.validate.call(this, param); //pass param, not inputs
}
function EventViewSimpleValidator() {}
EventViewSimpleValidator.prototype = Object.extend(Validator.prototype); //inheritance
EventViewSimpleValidator.prototype.constructor = EventViewSimpleValdiator; //enforce the constructor to point to your derived type
EventViewSimpleValidator.prototype.validate = function() {
var inputs = $('inputs');
var param = 'do some stuff specific to EventViewSimpleValidator based on the inputs';
return Validator.prototype.validate.call(this, param); //pass param, not inputs
}
function EventViewTabs() {
this.validator = null; //see init
}
EventViewTabs.prototype.init = function() {
this.validator = new EventViewTabsValidator();
}
function EventViewSimple() {
this.validator = null; //see init
}
EventViewSimple = function() {
this.validator = new EventViewSimpleValidator();
}
您可以将这两种类型抽象为一个基 EventView
,这可以公开 this.validator
。
您的 EventController
实例将调用:
var simple = new EventViewSimple();
simple.validator.validate();
var tabs = new EventViewTabs();
tabs.validator.validate();
无论 EventView
实例是什么,它们都实现了自己的特定验证器,可以以通用方式调用。
我有一个 JavaScript MVC 设计,使用原型实现,其中不同的项目可以根据控制器的决定以不同的方式显示。例如,一个 'Event' 项目可能会与视图 ViewTabs
或 ViewSimple
一起显示。 Class 层级:
ViewBase
- ViewTabs
-- EventViewTabs, which implements EventViewTabs.Validate
- ViewSimple
-- EventViewSimple, which implements EventViewSimple.Validate
决定是使用 EventViewTabs
还是 EventViewSimple
是由 EventController
完成的。我的问题是:我有一个 Validate
方法来检查来自 Event
视图的输入,但是这个方法对于 EventViewTabs
和 EventViewSimple
视图是相同的。我应该把 Validate
放在哪里以避免重复?我不能把它放在 ViewBase
中,因为其他项(例如 User
)也继承自此 class。
看来我需要多重继承,但有更聪明的方法吗?我有一种感觉,我忽略了一些明显的东西。
一种方法是使用 mixin 添加其他行为(这是 ruby 方法,react.js 和 react.rb 也使用这种方法)您可以 google 对于 javascript+mixins 并找到一些像这样的优秀教程:http://raganwald.com/2014/04/10/mixins-forwarding-delegation.html
对于您的具体情况,validate
(或者可能 validator
)将是 mixin。
为什么不做这样的事情: ViewBase
ViewBase
-EventValidator, which implements Validate
--ViewTabs
---EventViewTabs
--ViewSimple
---EventViewSimple.
还考虑使用组合而不是继承,请参阅this video
您缺少作文。继承并不能解决有关代码重用的所有问题,以避免 copy-paste 编程.
假设您有一个 View
基本原型:
function View() { }
如果想让这个视图支持校验,可以在构造函数中注入校验依赖:
function View(validator) {
this.validator = validator;
}
View.prototype = {}; // A lot of functions here
也就是说,现在任何继承 View
原型的视图都将有一个关联的验证器。换句话说:你不需要在你的具体视图中派生两个原型(你不需要也做不到)。
另一方面,就 object-oriented 编程而言,从 Validator
派生以创建 View
是没有意义的。
当你说 视图有验证器 时,因为你使用 has 作为动词,所以你在谈论关联(组合的一种形式)。或者,当您说 我的主屏幕 是 作为视图 时,我们在谈论 继承 , 因为一个特定的视图必须也是一个视图,所以它需要基础视图的成员像一个视图一样。
基本上,您的验证器可以 tailor-made 具有它必须使用的类型。在 UML 中,它被称为组合。我计算出你的代码如下:
function Validator {}
Validator.prototype.validate = function(arg) {
//arg is no longer inputs
return true|false; //the ultimate output along with additional information;
}
function EventViewTabsValidator() {}
EventViewTabsValidator.prototype = Object.extend(Validator.prototype); //inheritance
EventViewTabsValidator.prototype.constructor = EventViewTabsValidator; //enforce the constructor to point to your derived type
EventViewTabsValidator.prototype.validate = function() {
var inputs = $('inputs');
var param = 'do some stuff specific to EventViewTabsValidator based on the inputs';
return Validator.prototype.validate.call(this, param); //pass param, not inputs
}
function EventViewSimpleValidator() {}
EventViewSimpleValidator.prototype = Object.extend(Validator.prototype); //inheritance
EventViewSimpleValidator.prototype.constructor = EventViewSimpleValdiator; //enforce the constructor to point to your derived type
EventViewSimpleValidator.prototype.validate = function() {
var inputs = $('inputs');
var param = 'do some stuff specific to EventViewSimpleValidator based on the inputs';
return Validator.prototype.validate.call(this, param); //pass param, not inputs
}
function EventViewTabs() {
this.validator = null; //see init
}
EventViewTabs.prototype.init = function() {
this.validator = new EventViewTabsValidator();
}
function EventViewSimple() {
this.validator = null; //see init
}
EventViewSimple = function() {
this.validator = new EventViewSimpleValidator();
}
您可以将这两种类型抽象为一个基 EventView
,这可以公开 this.validator
。
您的 EventController
实例将调用:
var simple = new EventViewSimple();
simple.validator.validate();
var tabs = new EventViewTabs();
tabs.validator.validate();
无论 EventView
实例是什么,它们都实现了自己的特定验证器,可以以通用方式调用。