`
邦者无敌
  • 浏览: 11636 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

Javascript的类实现--------封装、抽象与继承

阅读更多

一.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();

           }

 

 

分享到:
评论

相关推荐

    JavaScript教程--从入门到精通

    JavaScript,是一种轻量级的解释型编程语言,广泛应用于网页和网络应用开发,实现客户端的动态效果和交互。本教程将全面深入地介绍JavaScript的核心概念和技术,帮助学习者从零基础逐渐达到精通的程度。 首先,...

    第5章-Java类的继承、抽象类和接口.doc

    接口中的方法都是抽象的,必须在实现类中被实现。 例如,下面是一个简单的接口示例: ```java public interface Printable { void print(); } public class Document implements Printable { public void print...

    The Principles of Object Oriented.JavaScript

    - **原型链继承**:JavaScript使用原型链实现继承机制,每个对象都有一个指向其原型对象的链接,当查找一个对象的属性时,如果该对象自身不存在该属性,则会沿着原型链向上查找。 - **构造函数**:虽然JavaScript不...

    javascript 经典面向对象设计

    - **类与继承**:ES6中的`class`语法提供了一种更加直观的方式来定义类和实现继承。例如: ```javascript class Animal { constructor(name) { this.name = name; } speak() { console.log(this.name + ' ...

    js 实现类式继承

    在JavaScript中,实现类式继承是面向对象编程中的一个关键概念。JavaScript本身是一种基于原型的动态类型语言,但在ES6引入了`class`语法糖,使得类的概念更加清晰,但其实质仍然是基于原型的继承。下面我们将深入...

    javascript-978-1-7858-8216-6:掌握 JavaScript 设计模式 - 第二版

    最后,本书可能还会涉及一些现代JavaScript特性如何与设计模式结合,如箭头函数、类和模块系统(ES6+)。这些新特性使得JavaScript更接近传统的面向对象语言,同时也引入了新的设计模式可能性。 通过学习这本书,...

    clean-code-javascript

    类是面向对象编程的核心概念之一,在JavaScript中,虽然它不是原生支持的,但可以通过构造函数和原型继承来实现。 ##### 1. 封装 确保类的内部状态被良好地封装,并通过公共方法暴露对外的行为。 ##### 2. 继承 ...

    Javascript继承[参考].pdf

    在深入理解JavaScript继承之前,我们需要掌握几个核心概念:父类(也称作超类)是指被继承的类,子类是通过继承父类得到的类,抽象类通常不用于实例化,而是作为其他类继承的基础,基类是提供给其他类继承的类,派生...

    javascript-class-hw

    在JavaScript中,类是ES6引入的一种新的语法糖,它实际上是对原型继承的语法层面上的封装,使得代码更加易读和易写。在这个"javascript-class-hw"的学习材料中,我们将深入探讨JavaScript的类和对象机制。 首先,...

    Object_Oriented_Javascript

    在JavaScript中,可以通过函数作用域或者ES6类来实现封装。 - **继承**:允许一个对象继承另一个对象的属性和方法。JavaScript通过原型链实现继承,这是一种动态继承机制。 - **多态**:指子类可以重写父类的方法,...

    Javascript 面向对象的JavaScript进阶

    在探讨面向对象的JavaScript之前,我们首先需要了解面向对象编程(Object-Oriented Programming, OOP)的基本特性:封装性、抽象性、继承性和多态性。 ##### 8.1.1 封装性 **定义:** 封装性是面向对象编程的一个...

    SHEIN 2022届-后台开发笔试题(B卷)

    - **用途**:抽象类主要用于提供一个通用的模板供其他类继承,从而实现代码重用。 - **注意事项**: - 抽象类可以有非抽象方法。 - 抽象类可以有构造器。 - 如果一个类包含了抽象方法,则这个类也必须声明为抽象...

    JavaScript-design-patterns:JavaScript 设计模式

    - 命令模式:将命令封装为对象,以便调用者与接收者解耦。 - 解释器模式:实现简单的语言或表达式的解释器。 - 迭代器模式:提供一种方法顺序访问集合对象的元素,而不暴露其底层表示。 - 中介者模式:简化多个...

    Advanced JavaScript

    - 封装与抽象的重要性。 - 高级OOP设计模式的应用。 ### 五、函数与变量作用域 《函数与变量作用域》章节,深入分析了JavaScript中函数的细节以及作用域规则。这可能包括: - 函数声明与表达式的区别。 - 闭包的...

    ud989-JavaScript-Design-Patterns:JavaScript 设计模式

    4. **原型模式**:JavaScript的原型继承机制是其独特的特性,允许一个对象直接继承另一个对象的属性和方法。通过`__proto__`或`Object.create()`可以实现原型链。 5. **观察者模式**(发布/订阅):当一个对象的...

    Design pattern In JavaScrip-design-pattern-in-javascript.zip

    - **桥接模式**:将抽象部分与实现部分分离,使它们可以独立变化。 - **组合模式**:将对象组合成树形结构以表示“部分-整体”的层次结构,使得用户对单个对象和组合对象的使用具有一致性。 - **外观模式**:为子...

    java1000题基础百战程序员

    - 面向对象的基本概念:封装、继承、多态 - 类与对象 - 构造方法与析构方法 - 继承与抽象类 - 接口与实现 - **异常机制** - 异常处理的重要性 - try-catch-finally结构 - 自定义异常 - 检查性异常与运行时...

Global site tag (gtag.js) - Google Analytics