Javascript中的多重继承与原型链

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Javascript中的多重继承与原型链相关的知识,希望对你有一定的参考价值。

我有一个javascript MVC设计,使用原型实现,其中不同的项目可以由控制器决定的不同方式显示。例如,可以使用视图ViewTabsViewSimple显示“事件”项。类层次结构:

ViewBase
- ViewTabs 
-- EventViewTabs, which implements EventViewTabs.Validate
- ViewSimple
-- EventViewSimple, which implements EventViewSimple.Validate

决定是否使用EventViewTabsEventViewSimple是由EventController完成的。我的问题是:我有一个Validate方法来检查来自Event视图的输入,但这种方法对于EventViewTabsEventViewSimple视图是相同的。我应该把Validate放在哪里以避免重复?我不能把它放在ViewBase,因为其他项目(例如User)也从这个类继承。

似乎我需要多重继承,但是有更聪明的方法吗?我有一种感觉,我忽略了一些明显的东西。

答案

基本上,您的验证器可以根据其必须使用的类型进行定制。在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实例是什么,它们都会实现自己的特定验证器,可以通用方式调用。

另一答案

你错过了作文。对于避免复制粘贴编程的代码重用的所有问题,继承不是答案。

假设你有一个View基础原型:

function View() { }

如果您希望此视图支持验证,则可以在构造函数中注入验证依赖项:

function View(validator) {
   this.validator = validator;
}
View.prototype = {}; // A lot of functions here

也就是说,现在任何继承View原型的视图都会有一个相关的验证器。换句话说:您不需要在具体视图中派生出两个原型(您不需要也无法完成)。

另一方面,在面向对象编程方面,从Validator派生出来创建一个View是没有意义的。

当你说一个视图有一个验证器,因为你使用has作为动词,你谈论的是一个关联(一种组合形式)。或者,当您说我的主屏幕是视图时,我们讨论的是继承,因为特定视图也必须是视图,因此它需要基本视图的成员像视图一样工作。

另一答案

一种方法是使用mixins来添加其他行为(这是ruby方法,并且也被react.js和react.rb使用)你可以谷歌搜索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

以上是关于Javascript中的多重继承与原型链的主要内容,如果未能解决你的问题,请参考以下文章

JavaScript中的原型与原型链

JavaScript原型链的理解

javascript的继承与原型链

javascript类继承系列二(原型链)

JavaScript继承与原型链

javascript 原型链实现继承简单例子