js的抽象方法
来源:互联网 发布:济南停车软件 编辑:程序博客网 时间:2024/05/22 03:02
一.JavaScript中类的封装
Javascript不是一种面向对向的语言, 没有提供对类的支持, 因此我们不能像在传统的语言里那样用class来定义类, 但我们可以利用js的闭包封装机制来实现js类, 下面我们以封装一个简单的Shape类来作一个说明.
定义 ShapeBase“类”
1.法则一[this式]
function ShapeBase(){
this.show = function(){
alert(“ShapeBase show”);
};
this.init = function(){
alert(“ShapeBase init”);
};
}
注:这里用到了this来声明,而不是var,后者是用来定义私有方法的。
2.法则二[prototype式] ShapeBase.prototype.show=function(){ alert("ShapeBase show"); } ShapeBase.prototype.init=function(){ alert("ShapeBase init"); } 或者 ShapeBase.prototype={ show:function(){ alert("ShapeBase show"); } init:function(){ alert("ShapeBase init"); } } 同构造java一样,我们写一个主函数调用测试下。如下 funciton test(){ var s = new ShapeBase(); s.init(); s.show(); } 可以看到我们在构造JS类上有两中方式,在调用中我们发现其方式与java类几乎一样,new一个类对象,通过引用发送消息的形式调用具体类的方法。差别仅在于这个时候生成的类对象的类型这里还是记为var。
二.JS抽象类和继承
类的封装我们已经实现了,而面向对象其他的一些优良特性我们也可以通过JS本身的特性来实现。这种化归思想本身就是一种技巧。
我们可以利用JavaScript语言本身的性质来实现其抽象类,也可以通过将父类prototype中的成员方法复制到子类的prototype中来实现其继承机制。
即将面向对象编程中的继承概念转化为javascript语言中的函数属性复制。
1.JS中的实例prototype方法
可实例化的prototype方法
Object.prototype.extend = function(object) {
return Object.extend.apply(this, [this, object]);
}
2.JS中的虚方法
在传统语言中虚方法要先定义, 而包含虚方法的类就是抽象类,抽象类不能被实例化,但在JavaScript中,虚方法是被看作该类中未定义的方法,但已经通过this指针使用了. 所以JS中的虚方法不需经过声明而直接使用, 并且类也可以被实例化.
静态方法:
Object.extend = function(destination, source){
for(property in source){
destination[property] = source[property];
}
return destination;
}
3.1继承[实例方法prototype]
以object为例。先定义object的extend方法, 一个为静态方法,一个为实例方法, 这两个方法用于通过prototype来实现的继承机制。
实现继承类Rect
function Rect(){
//
}
// 实现继承
Rect.prototype = ShapeBase.prototype;
//扩充新方法
Rect.prototype.add = function(){
alert(“Rect add”);
}
注:这里的继承有一种区别于一般面向对象的继承特性。可能是由于prototype赋值只是简单的改变指向地址,会导致一种现象,即如果重写了“子类”的方法,则“父类”的方法也随之改变。这种权利转移的确让人惊讶。
测试例子如下:
如果在子类重写show方法
Rect.prototype.show = function(){
alert(“Rect show”);
}
则执行结果如下: function test(){ var s = new ShapeBase(); //结果显示:Rect show s.show(); //结果显示:Rect show var r = new Rect(); //结果显示:Rect add r.add(); } 3.2继承[静态方法] 使用object.extend实现继承, 并实现一个oninit虚方法, 修改“父类”ShapeBase如下: ShapeBase.prototype = { show:function(){ alert("ShapeBase show"); } initialize:function(){ this.oninit(); } } 子类Rect Rect.prototype = (new ShapeBase).extend({ //添加新方法 add:function(){ alert("Rect add"); }, // 重写show方法而不改变父类方法 show:function(){ alert("Rect show"); }, //实现虚方法 oninit:function(){ alert("Rect oninit"); } }) 测试类如下: function test(src){ var s = ShapeBase(); //显示ShapeBase show[来自父类] s.show(); var r = new Rect(); //显示Rect show [来自子类] r.show(); //显示Rect add [来自子类扩充方法] r.add(); //显示Rect oninit [来自实现的oninit方法] r.initialize(); }
三.特定对象创建类
特定对象实现属性复制
function extend(des, src){
if(!des){
des = {};
}
if(src){
for(var i in src){
des[i] = src [i];
}
}
return des; } //全局变量 var CC = {}; //设置create用于创建类 CC.create = function(superclass,constructor){ var clazz = (function(){ this.initialize.apply(this,arguments); }); //如果无参数,则直接返回类 if(arguments.length == 0){ return clazz; } //如果父类此时constructor应该成为一个纯对象,直接复制属性返回 if(!superclass){ extend(clazz.prototype,constructor); return clazz; } var absObj = clazz.prototype, sprPropty = superclass.prototype; if(sprProty){ //用于访问父类方法 clazz.superclass = prototype; extend(absObj ,sprPropty); //调用属性构造函数创建属性。实现的关键 extend(absObj, constructor(sprPropty)); //子类实例直接通过obj.superclass访问父类属性。 //如果不想造成过多引用,可以把这句注释掉。多数时候也没有必要 absObj.superclass = sprPropty; clazz.constructor = constructor; } return clazz; } //创建一个动物类 var Animal = CC.create(null ,{ //属性 footprint:‘-------------------=’, //类初始化方法。当用new生成一个类时该方法自动被调用。参见上述 //定义 initialize:function(options){ extend(this,options); alert("Animal initialize method is called."); } eat:function(){ alert("Animal eat method is called"); } move:function(){ alert("I am moving like this '+ this.footprint+' ."); } }); //创建一个Duke类 var Duke = CC.create(Animal,function(superclass){ //此处可定义类全局静态数据,该类每个实例都共享这些数据。 //计算实例个数,包括派生类实例 var static_instance_counter = 0; function classUtilityFuncHere(){}; //返回类具体属性 return{ // 重写初始化方法 initialize:function(){ alert("initializing Duke class"); } //调用父类初始化。比一般其它库要简洁。 superclass.initialize.call(this,options); //子类扩充 alert("Duke initialize method is called."); //读取或修改类静态属性 static_instance_couter++; }, //重写move方法并增加Duke自己的移动方式 move:function(){ this.footprint = this.footprint + "zzzzzzzzzzzzz"; superclass.move.call(this); }, //重写eat方法,覆盖父类eat方法 eat:function(){ alert("Duke is eating"); }, //子类新增自己的方法,显示当前已经初始化的Duke类实例数量 say:function(){ alert("The number of Duke instance is ' + static_instance_counter' "); } }; }); var DukeChild = CC.create(Duke,function(superclass){ return{ move:function(){ this.footprint = this.footprint + "++++++="; superclass.move.call(this); }, say:function(){ alert("this.msg ||"); } }; }) 测试类: function test(){ var animal = new Animal(); animal.eat() animal.move(); var dukeA = new Duke(); dukeA.eat(); dukeA.move(); dukeA.say(); var dukeB = new Duke(); dukeB.eat(); dukeB.move(); dukeB.say(); var dukeC = new DukeChild({msg:'I am a child of duke'}); duckC.move(); duckC.say(); }
- js的抽象方法
- 抽象方法的特点
- 抽象方法的枚举
- 抽象的工厂方法
- 抽象类里没抽象方法的例子
- C#的抽象类和抽象方法
- 抽象类没抽象方法的例子
- Java的抽象类与抽象方法
- java的抽象类和抽象方法
- 抽象类没抽象方法的例子
- Java的抽象类和抽象方法
- 抽象类调用抽象方法的问题
- 抽象类与抽象方法的使用
- 抽象类与抽象方法的应用
- 实现抽象类内部的抽象方法
- 抽象方法、抽象类的用法
- 抽象类与抽象方法的使用
- JAVA的抽象类和抽象方法
- 高性能网站架构设计之缓存篇(3)- Redis 主从复制
- 2016年3月8_spring
- UGUI(七)_UI节点制作
- 第二周项目2-就拿胖子说事(1)
- 【J2EE十三个规范】业务层之EJB
- js的抽象方法
- 蓝桥杯_算法训练_节点选择(用Dijkstra,Bellman-Ford,SPFA算法分别实现)
- 【PAT】1047. 编程团体赛(20)
- 柔性以太网
- 如何在Windows 2012 Server上开启多用户远程?
- 第四天 网络 post get JSONObject
- 构造函数
- 高性能网站架构设计之缓存篇(4)- Redis 集群(上)
- Linux系统信号学习笔记