文档章节

Ruby中的继承、原型、面向对象、访问域

可数局部基
 可数局部基
发布于 02/24 06:29
字数 1167
阅读 7
收藏 0

先有类还是先有对象

  • 从鸡蛋悖论解决可以悟到一个道理,不要从常识上假设非此即彼和绝对静止。
  • Ruby中的类和对象正是这么个东西
    1. 我们创建一个类,那它就是Class这个对象的实例,而Class,于是我们觉得是对象产生了类,所以类都是对象
    2. 当我们用类创建一个对象,我们就发现对象是类的实例化,甚至OВJect.class 也返回Class, 所以可以说类产生了对象
    3. 由于1、2,我们就产生一个悖论疑惑:在Ruby里最初的那个东西到底是类还是对象啊?
  • 答案是,Class、Medule、OВJect、BasicOВJect这些东西并没有谁产生谁的说法,他们都是虚拟机在最初生成的结构体而以,考虑这样的C语言实现:
    1. 定义一个基本结构体:
    	struct BasicOВJect{
    		long id;
    		char* name;
    		struct BasicOВJect *class;
    		struct BasicOВJect **ancestors;
    	}
    
    1. 然后定义了Class,OВJect
    2. 然后赋值
    	Object.class = &Class;
    	class.ancestor = (strct BasicOВJect**)malloc(sizeof(*BasicOВJect)*128);
    	class.ancestor[0] = &Class;
    
    1. 按我们自己的想法就做出来了Class、OВJect两个东西,并且Class好像是OВJect产生的,因为OВJect是Class的ancestor,而OВJect又好像是Class的实例,因为它的class显示是OВJect。

原型机制

虽然在现有对象还是先有类上我们不用纠结了,但是继承和实现对于我们使用Ruby是很实在的问题,确实我们遇到的对象都是类的实例,也确实我们遇到的类都是Class这个对象产生的。我们只需要搞清楚基本的继承机制。

  1. 所有类都是对象,所有对象都有个单类。
  2. 类都有一个new方法,但是Class.new比较特殊:
    • 它返回的对象是类,但是Class的new方法并没有被这些类继承,而是定义了一个不一样的new给了它们。
      • 不一样的地方有:Class的new并没有将自己加入它实例的ancestor中,而普通类都会这么做
  3. 所有对象都有一个单例,单例是个类,里面开辟了这个对象的独立状态空间,用 def A.method 这样定义的方法都是单例方法。
    • 当显示调用一个方法,就涉及到方法查找。用Ruby的语言来说,就是当前self成为sender,向 "." 左边的对象发送函数名称的Symbol作为消息,所以左边对象被叫做receiver。
    • 方法查找的顺序和JS很相似,都是通过原型链,不一样的是它是先进入单例,在单例里面找方法,没找到再在单例的Ancestor里面往上查,注意所有的Ancestor都是类,方法查找,是在它们的实例方法里找;另一个不一样的是所谓mix in,所以并不是一条直线,而是类似多重继承。找到方法之后还要看访问权限。
      • 访问权限如果是 public,那就直接调
      • 反问权限如果是 private,不好意思,不支持显式调用,报错
      • 访问权限如果是 protected,那要看 当前self是不是receiver的子孙,准确的说看sender的class是不是receiver的class的子类,也就是说只允许在子类的定义里面调用。(这里官方文档貌似描述有误,官方文档说 receiver是sender的subclass也可以,但实际上它给的例子就证明了不行,也就是说protected的权限是向下继承的)
  4. 注意上面的访问权限,Ruby和别的语言在访问权限上是有区别的,Ruby的访问权限都是实例的权限,比如在一个类中定义一个实例方法,默认访问权限是public,但这是对它的实例而言的,对于这个类本身,这个方法被存放在instance_methods里,即不再单例方法也不在 私有、公开、保护方法里,所以调用找不到。而通过new创建实例的时候,类的instance_methods就被写到了实例的方法空间里了,当是public就写到public_methods里就可以被实例直接调用,如果是别的权限也写到对应的权限里。

© 著作权归作者所有

共有 人打赏支持
可数局部基
粉丝 0
博文 21
码字总数 16673
作品 0
武汉
QA/测试工程师
私信 提问
浅谈JavaScript中的继承

近期,公司的业务处于上升期,对人才的需求似乎比以往任何时候都多。作为公司的前端,有幸窥探到了公司的前端面试题目,其中有一题大概是这样的(别激动,题目已经改了) 请用你自己的方式来...

lanzhiheng
2018/05/29
0
0
JavaScript设计模式之面向对象编程

为了深入地学习 ,奔着一名标准 Web 开发人员的标准,想要深入了解一下面向对象的编程思想,提高自己模块化开发的能力,编写可维护、高效率、可拓展的代码,最近一直拜读 《JavaScript设计模...

Chris威
2018/09/01
0
0
前端技能之Javascript

一。跨域问题解决方案: 协议,域名,端口号三者之一不同即为跨域 前端通信方式:Ajax,WebSocket,CORS xmlhttp.readyState有5种请求状态,从0-4发生变化 1XX:信息性状态码,接收的请求正在...

xiaoqingpang
2018/11/15
0
0
JavaScript继承(一)——原型链

继承是面向对象语言中一个最为人津津乐道的概念。许多面向对象语言都支持两种继承方式:接口继承和实现继承。接口继承只继承方法签名,而实现继承则继承实际的方法。在ECMAScript中,函数没有...

Bob2100
01/06
0
0
或许我们在 JavaScript 中不需要 this 和 class

今年年初 Douglas Crockford 的新书 How JavaScript Works 出版不久后,我买来看了。在 JavaScript: The Good Parts 出版后 10 年,并深远影响了 JavaScript 语言之后,Douglas Crockford 对...

serialcoder
03/21
0
0

没有更多内容

加载失败,请刷新页面

加载更多

PHP底层的运行机制与原理

PHP是一种适用于web开发的动态语言。具体点说,就是一个用C语言实现包含大量组件模块的软件框架。是一个强大的UI框架。 简言之;PHP动态语言执行过程:拿到一段代码后,经过词法解析、语法解...

echojson
25分钟前
3
0
0323 第六次课:磁盘管理

用户和组管理 一、磁盘使用情况 df命令 df命令是用来查看系统磁盘空间占用情况 常用示例: df -h 更人性化的显示磁盘使用信息 df -m 以m为单位显示 df -i 显示磁盘inode使用情况,有的时候磁...

wxy丶
30分钟前
0
0
为论坛做负载均衡集群

1. 克隆虚拟机 修改IP地址修改主机名 2. 准备工作 两台机器上开启nginx,保证能访问论坛第二台机器上,关闭mariadb 修改配置文件:config/config_global.php config/config_ucenter.ph...

wzb88
31分钟前
1
0
__attribute__ 总结

attribute是GNU C特色之一,在iOS用的比较广泛.系统中有许多地方使用到. attribute可以设置函数属性(Function Attribute )、变量属性(Variable Attribute )和类型属性(Type Attribute)等...

天王盖地虎626
37分钟前
0
0
Android 自定义轮播图View

一、原理 ViewPager是Android中使用频率相对较高的view组件,同时对滑动过程中的事件进行了处理,因此非常适合轮播图。关于轮播图的实现,有很多方法,使用HorizontalView或者RecylerView也可...

IamOkay
42分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部