【cocos2d-x从c++到js】06:Google的继承写法解析

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介:

cocos2d-x for js中集成了两套继承写法,一套是JR的,一套是google。公司同事使用过node.js,对google的继承方式比较赞同。我就看了一下Google的继承代码。

先贴代码:

 
  1. // 1) Google "subclasses" borrowed from closure library 
  2. // This is the recommended way to do it 
  3. // 
  4. cc.inherits = function (childCtor, parentCtor) { 
  5.     /** @constructor */ 
  6.     function tempCtor() {}; 
  7.     tempCtor.prototype = parentCtor.prototype; 
  8.     childCtor.superClass_ = parentCtor.prototype; 
  9.     childCtor.prototype = new tempCtor(); 
  10.     childCtor.prototype.constructor = childCtor; 
  11.  
  12.     // Copy "static" method, but doesn't generate subclasses. 
  13. //  for( var i in parentCtor ) { 
  14. //      childCtor[ i ] = parentCtor[ i ]; 
  15. //  } 
  16. }; 

cc.inherits是继承函数,负责链接父类和子类的原型链。非常有趣的是,在这里使用了一个临时构造器,这样就替换了JR代码中的initializing 写法。看起来很舒服。

 

 
  1. cc.base = function(me, opt_methodName, var_args) {  
  2.     var caller = arguments.callee.caller;  
  3.     if (caller.superClass_) {  
  4.         // This is a constructor. Call the superclass constructor.  
  5.         ret =  caller.superClass_.constructor.apply( me, Array.prototype.slice.call(arguments, 1));  
  6.         return ret;  
  7.     }  
  8.   
  9.     var args = Array.prototype.slice.call(arguments, 2);  
  10.     var foundCaller = false;  
  11.     for (var ctor = me.constructor;  
  12.         ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {  
  13.         if (ctor.prototype[opt_methodName] === caller) {  
  14.             foundCaller = true;  
  15.         } else if (foundCaller) {  
  16.             return ctor.prototype[opt_methodName].apply(me, args);  
  17.         }  
  18.     }  
  19.   
  20.     // If we did not find the caller in the prototype chain,  
  21.     // then one of two things happened:  
  22.     // 1) The caller is an instance method.  
  23.     // 2) This method was not called by the right caller.  
  24.     if (me[opt_methodName] === caller) {  
  25.         return me.constructor.prototype[opt_methodName].apply(me, args);  
  26.     } else {  
  27.         throw Error(  
  28.                     'cc.base called from a method of one name ' +  
  29.                     'to a method of a different name');  
  30.     }  
  31. };  

cc.base是在子类函数中调用父类同名函数的方法。要使用这个函数,必须是使用过cc.inherits进行过链接原型链的类才行。参数方面,me需要传入this,其他根据形参表来定。

 
  1. var caller = arguments.callee.caller; 

首先通过,上面的代码获得外层函数的对象。(据说caller这个属性已经不再建议使用了,不知道是什么原因)。

然后,如果外层函数是构造函数的话,一定是存在superClass_这个属性的。那么可以用apply调用父类的构造器,然后就退出函数执行就可以了。(但是这里为什么会有返回值呢,他喵的构造器返回值不是被运行环境给接管了么?)

 
  1. var args = Array.prototype.slice.call(arguments, 2);   
  2.     var foundCaller = false;   
  3.     for (var ctor = me.constructor;   
  4.         ctor; ctor = ctor.superClass_ && ctor.superClass_.constructor) {   
  5.         if (ctor.prototype[opt_methodName] === caller) {   
  6.             foundCaller = true;   
  7.         } else if (foundCaller) {   
  8.             return ctor.prototype[opt_methodName].apply(me, args);   
  9.         }   
  10.     }   

如果外层函数不是构造函数,那么就是子类的普通函数。后面的代码也很简单,从子类向上往父类上面找,一层一层的遍历构造器,然后再核对同名函数,如果在当前层次找到了对应的函数名,就在下一轮循环中,调用父类的同名函数即可。然后直接返回。

 
  1. if (me[opt_methodName] === caller) {   
  2.         return me.constructor.prototype[opt_methodName].apply(me, args);   
  3.     } else {   
  4.         throw Error(   
  5.                     'cc.base called from a method of one name ' +   
  6.                     'to a method of a different name');   
  7.     }   

如果要调用的那个函数,既不是构造函数,也不是父类中的同名函数。那么只有一种可能,就是这个函数是子类的一个实例上的函数。直接apply调用就好了。

再找不到的话,代码就会抽风了。(throw Error)

 

综上,google的代码风格非常流畅,可读性也很高。如果JR是很黄很暴力,各种奇技淫巧不计其数。那么google的代码就是和风细雨,润物细无声。

就我个人而已,非常喜欢JR的接口,但是又喜欢google的内部实现。矛盾啊,喵了个咪。

另外,google的代码可以做到很容易的和其他继承机制兼容,但JR的就不行,必须已自己为核心来搞才可以的。这些是由他们的实现机制决定的。

目前来说,cocos2d-x for js使用JR的写法,不知道会不会对将来的扩展造成一些问题呢。

 

 


 本文转自 老G 51CTO博客,原文链接:http://blog.51cto.com/goldlion/1127112,如需转载请自行联系原作者


相关文章
|
3月前
|
JavaScript 前端开发 Go
CSS 与 JS 对 DOM 解析和渲染的影响
【10月更文挑战第16天】CSS 和 JS 会在一定程度上影响 DOM 解析和渲染,了解它们之间的相互作用以及采取适当的优化措施是非常重要的。通过合理的布局和加载策略,可以提高网页的性能和用户体验,确保页面能够快速、流畅地呈现给用户。在实际开发中,要根据具体情况进行权衡和调整,以达到最佳的效果。
|
2月前
|
JavaScript 前端开发
如何在 JavaScript 中使用 __proto__ 实现对象的继承?
使用`__proto__`实现对象继承时需要注意原型链的完整性和属性方法的正确继承,避免出现意外的行为和错误。同时,在现代JavaScript中,也可以使用`class`和`extends`关键字来实现更简洁和直观的继承语法,但理解基于`__proto__`的继承方式对于深入理解JavaScript的面向对象编程和原型链机制仍然具有重要意义。
|
9天前
|
C++ 开发者
C++学习之继承
通过继承,C++可以实现代码重用、扩展类的功能并支持多态性。理解继承的类型、重写与重载、多重继承及其相关问题,对于掌握C++面向对象编程至关重要。希望本文能为您的C++学习和开发提供实用的指导。
42 16
|
5天前
|
编译器 数据安全/隐私保护 C++
【C++面向对象——继承与派生】派生类的应用(头歌实践教学平台习题)【合集】
本实验旨在学习类的继承关系、不同继承方式下的访问控制及利用虚基类解决二义性问题。主要内容包括: 1. **类的继承关系基础概念**:介绍继承的定义及声明派生类的语法。 2. **不同继承方式下对基类成员的访问控制**:详细说明`public`、`private`和`protected`继承方式对基类成员的访问权限影响。 3. **利用虚基类解决二义性问题**:解释多继承中可能出现的二义性及其解决方案——虚基类。 实验任务要求从`people`类派生出`student`、`teacher`、`graduate`和`TA`类,添加特定属性并测试这些类的功能。最终通过创建教师和助教实例,验证代码
22 5
|
3月前
|
存储 前端开发 JavaScript
JavaScript垃圾回收机制深度解析
【10月更文挑战第21】JavaScript垃圾回收机制深度解析
131 59
|
2月前
|
编译器 C++ 开发者
【C++】继承
C++中的继承是面向对象编程的核心特性之一,允许派生类继承基类的属性和方法,实现代码复用和类的层次结构。继承有三种类型:公有、私有和受保护继承,每种类型决定了派生类如何访问基类成员。此外,继承还涉及构造函数、析构函数、拷贝构造函数和赋值运算符的调用规则,以及解决多继承带来的二义性和数据冗余问题的虚拟继承。在设计类时,应谨慎选择继承和组合,以降低耦合度并提高代码的可维护性。
39 1
【C++】继承
|
2月前
|
JavaScript 前端开发
Javascript如何实现继承?
【10月更文挑战第24天】JavaScript 中实现继承的方式有很多种,每种方式都有其优缺点和适用场景。在实际开发中,我们需要根据具体的需求和情况选择合适的继承方式,以实现代码的复用和扩展。
|
2月前
|
JavaScript 前端开发
如何使用原型链继承实现 JavaScript 继承?
【10月更文挑战第22天】使用原型链继承可以实现JavaScript中的继承关系,但需要注意其共享性、查找效率以及参数传递等问题,根据具体的应用场景合理地选择和使用继承方式,以满足代码的复用性和可维护性要求。
|
2月前
|
JavaScript 前端开发 开发者
js实现继承怎么实现
【10月更文挑战第26天】每种方式都有其优缺点和适用场景,开发者可以根据具体的需求和项目情况选择合适的继承方式来实现代码的复用和扩展。
35 1
|
2月前
|
JavaScript 前端开发 API
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
Vue.js响应式原理深度解析:从Vue 2到Vue 3的演进
75 0

推荐镜像

更多