`

在Javascript模拟实现接口、多继承[模式]

阅读更多

在其他语言中比如 C# Java ,接口方法在定义的时候都是未实现的,而我这里模拟的 JS 接口则是可以在定义的时候实现的。

定义接口:

var IC lass Manager = {

hasClass:function(className){},

addClass:function(className){}

} ;

定义菜单类:

var Men u = function(options){

this._element = null;

this.setXY = function(x,y){

if (x) this._element.style.left = x + 'px';

if (y) this._element.style.top = y + 'px';

}

};

定义菜单项类:

var Men uItem = function(){

this.setText = function(){

};

}

其实菜单类和菜单项类都是基于 HTMLElement 的抽象,因此如果要让他们可以灵活的定义 HTMLElement 样式,那么都需要一组管理 className 的方法。因此 Menu MenuItem 都需要实现 IClassManager 。辅助实现接口的方法:

var extend = function(dest, source){ // 实现接口

dest = self || {};

for (property in source) {

if (! dest[property] ) // 如果 dest 也就是类没有同名的方法,则用接口默认实现方法。

dest[property] = dest[property];

}

return dest;

}

extend(Menu.prototype, I Class Manager);

extend(MenuItem.prototype, I Class Manager);

这样 Menu MenuItem 都具有了 Class 的管理能力。

 

通过 extend Menu MenuItem 可以实现任意的接口,并且同时实现多个接口。

在实现接口之前 Menu MenuItem 还可以有一次继承的机会:

Menu.prototype = new BaseClass(); // 最简单的继承方式

然后再实现接口:extend(Menu.prototype, I Class Manager);

 

这样就类似单根继承 + 多接口实现,很像 C# 或者 Java

下面是完整的代码:

  (function(){

var Event = joyeach.util.Event;

var extend = function(dest, source){ // 实现接口

dest = self || {};

for (property in source) {

if (! dest[property] )

dest[property] = dest[property];

}

return dest;

}

//C lass Manager Interface

var I Class Manager= {

hasClass:function(className){

var reg = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)') ;

return reg.test(this._element['className']);

},

addClass:function(className){

if (this.hasClass(el, className))  return; 

this._element['className'] = [this._element['className'], className].join(' ');

}}

/**

* 菜单类

*/

joyeach.controls.Menu = function(options){

this._element = null;

this.setXY = function(x,y){

if (x) this._element.style.left = x + 'px';

if (y) this._element.style.top = y + 'px';

};

this.getXY = function(){

return [parseInt(this._element.style.left),

parseInt(this._element.style.top)];

};

this.addItem = function(item){

this._element.appendChild(item._element);

Event.fireEvent(this, 'onadditem', {sender:this, item:item});

};

this.getItemAt = function(index){

return this._element.childNodes[index]._control;

};

this.removeItemAt = function(index){

var element = this._element.childNodes[i];

this._element.removeChild(element);

Event.fireEvent(this, 'onremoveitem', {sender:this, item:element._control});

 

 

 

};

this.removeItem = function(item){

item._element.parentNode.removeChild(item._element);

Event.fireEvent(this, 'onremoveitem', {sender:this, item:item});

 

 

 

};

this.show = function(x,y){

if (x || y) this.setXY(x,y);

this._element.style.display = 'block';

Event.fireEvent(this, 'onshow', {sender:this});

};

this.hide = function(){

this._element.style.display = 'none';

Event.fireEvent(this, 'onhide', {sender:this});

 

 

 

};

this.close = function(){

this._element.parentNode.removeChild(this._element);

Event.fireEvent(this, 'onclose', {sender:this});

};

this._init = function(options){

this._element = document.createElement('div');

options = options || {};

if (options.css) this._element.className = options.css;

this.setXY(options.x,options.y);

//fire event onpopup

Event.fireEvent(this, 'onpopup', {sender:this});

document.body.appendChild(this._element);

};

//initialize menu

this._init(options);

};

 

/**

* 菜单项类.

*/

joyeach.controls.MenuItem = function(){

this.setText = function(){

};

this.getText = function(){

};

this.setTitle = function(){

};

this.getTitle = function(){

};

this._init = function(){

};

this._init();

};

//菜单类和菜单相类分别实现ICSSManager接口

extend(joyeach.controls.Menu.prototype, I Class Manager);

extend(joyeach.controls.MenuItem.prototype, I Class Manager);

})();

 

其中 IClassManager 接口方法实现里面的 this._element 可以在抽象成方法 this.getElement

 

此方案源于 prototype.js yahoo ui library

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics