`
xmou
  • 浏览: 5893 次
  • 性别: Icon_minigender_1
  • 来自: 成都
最近访客 更多访客>>
社区版块
存档分类
最新评论

Ruby对象模型与元编程(一)

 
阅读更多

 

Ruby看起来与众不同,基于一组精心设计的接口方法和作用域理论,形成了其优雅的语义模型。
但是万变不离其宗,了解了Ruby的对象模型,也就了解了其魔幻般的动态元编程原理。

[消息机制]

Ruby很好的继承和发扬了Smalltalk的面向对象理论。
在Ruby中,任何值是对象,原始类型如数字、字符串、布尔类型等是对象,甚至类和模块本身也是对象。
尽管对象的表示在形式上与一般数据类型十分相似,但是它们之间存在一种本质区别:对象之间通过消息传递方式进行交互。
对象交互的消息机制是面向对象更为本质的特征,为对象的交互提供了一种统一的形式,可以在运行时动态的创建消息,然后发送给合适的对象。

一般情况下,对象接收它能够识别的消息,拒绝它不能识别的消息。消息的名字就是这个对象公开的让外部可知的某个方法的名字。
由于类先于对象定义,
对象是类的实例,所以一个类为它的实例提供了可以预知的对外交互方式。


让我们想象一下如果发送一条对象不能识别的消息会怎样?
这种情况在C++、Java、C#等静态类型语言中会得到一个方法未定义的编译错误,在JavaScript中则会产生运行时异常,但是在Ruby这样的动态语言中却别有一片天地。

[对象模型]
在Ruby中,对象就是一组实例变量加上指向其类的引用。

对象的方法不存在于对象本身,而是存在于对象的类中。
类本身也是一个对象(Class类的实例),因此类也有自己的实例变量和指向其类的引用。

同时,类有一组实例方法和一个对其超类的引用。

正如你所熟悉的C++/Java等语言,典型的情况是先定义类,并创建一个该类的对象,然后向该对象发送消息。
在Ruby中,每一行代码都会在一个对象中执行,这个对象就是当前对象,用self表示。
在一个给定时刻,只有一个对象是当前对象。当前对象随着语句的执行而动态的变化,没有哪个对象能长期作为当前对象。
在任何时刻都知道哪个对象在充当self是绝对重要的。
Ruby中的类定义也是执行代码,而类也是一个对象,因此在类定义中,self就是正在定义的类。

同样的,在程序执行的过程中,也一直存在当前类。
Ruby会追踪当前类或模块的引用,所有使用def定义的方法都成为当前类的实例方法。
在类定义中,当前类就是正在定义的类。如果有一个类的引用,可以使用class_eval()打开这个类。

另一方面,Ruby允许给单个对象增加方法,称为单件方法。

也许你会想,如果每个对象都有自己的方法,那这些对象的类型不就乱套了吗?
事实上,面向对象封装的无非是数据和行为,要判断一个对象属于什么类型只需要关注对象表现出来的行为即可。这种将对象类型认为是其能响应的一组方法的概念称为duck typing。

我们知道对象的方法不存在于对象自身,那么对象的单件方法又存在于哪里?
为了优雅的解决duck typing和对象类型之间的矛盾,Ruby引入了eigenclass。
一个对象的单件方法实际上是与它关联的eigenclass的实例方法。而类方法,实际上就是类的单件方法。
每个对象(包括类)都有自己的”真正的类“,可能是eigenclass,也可能是普通的类。

那么对象什么时候有eigenclass? 
有2种情况,自动生成和显式生成。
在定义类的时候,Ruby会自动为你生成这个类的eigenclass,而其他的对象(包括模块)则需要显式生成。

普通的类与eigenclass之间又有什么关系?
一个对象的eigenclass的超类是这个对象的类,而一个类的eigenclass的超类是这个类的超类的eigenclass。
由于引入了eigenclass,Ruby的对象模型世界一下变得丰富多彩起来。

[方法调用]
说到方法调用,先来弄清楚方法修饰符public、protected与private。
Java中也有类似的方法修饰符,其中public作用一样,但是protected与private的区别很大:
Java中,任何方法都可以被同一个类型的其他对象调用;而Ruby中private方法不能被同一个类型的其他对象实例调用,因为不能明确指定一个接收者来调用私有方法。
Java中,private方法不能不继承;而Ruby中,不管protected还是private方法,都可以被子类继承。
为什么会有这样的行为差异呢?
Java强调继承关系,方法调用限定类继承的层次结构,但不限定同一类型的不同对象实例。
Ruby中一切皆对象,方法调用针对对象实例进行限定。不过虽然不能直接给私有方法指定接收者,也可以通过消息发送(send)来调用私有方法。

当调用一个方法时,也就是给一个对象发消息时,Ruby会怎样做?
首先,Ruby会把self设置为消息接收者,然后进入其”真正的类“进行方法查找,如果没找到则进入其祖先链一直往上查找。
如果找到了相应的方法,则以self为对象,调用该方法。如果一直到BasicObject都没找到这个方法,就会调用self的method_missing方法。
既然method_missing也是方法调用,那么又会进行新一轮的方法查找,所以覆盖method_missing方法就是元编程的一个重要手段。

经过方法查找,找到合适的方法后,就到了方法执行的阶段。
由于数据与方法是分开的,找到的方法只是可执行的代码而已。代码执行时需要一个执行环境,包括局部变量、实例变量、全局变量、常量、self等,也就是一组绑定。绑定存在于一个特定的作用域里面,而作用域会随着程序语句的执行进行动态切换。
Ruby有严格完整的作用域限制,程序会在三个地方进行作用域切换:类定义(class)、模块定义(module)、方法(def)。
可以使用Class.new()、Module.new()和define_method()分别代替class、module、def关键字,来避免作用域的切换。

搞清楚了对象、类、Eigenclass、作用域、消息、self、当前类等,也就搞清楚了Ruby的对象模型。


分享到:
评论

相关推荐

    面向对象的分布式脚本编程语言Reia.zip

    如果你既想要erlang的并发分布式编程的理念又不喜欢erlang丑陋的停留在80年代的那种语法,又想要现代的性感的漂亮的时尚的Ruby/Python式的面向对象观而不满意其并发模型,那么,可以尝试Reia. 标签:Reia

    Ruby 编程语言的书籍

    这本书涵盖了 Ruby 的基础知识和高级特性,包括对象模型、控制流、模块和类、异常处理、元编程等方面的内容。它适合初学者入门,同时也提供了一些进阶的话题,能够帮助读者系统地学习和掌握 Ruby 编程语言。

    Ruby高级编程教程-世界顶级高校教材(完整版827页)

    Ruby的一大优点是它与环境的集成度很高。 第二部分,Ruby在其环境中,对此进行了研究。在这里,您可以找到关于使用Ruby的实用信息:使用解释器选项、使用irb、记录您的Ruby代码,以及打包您的Ruby宝石,以便其他人...

    Ruby学习笔记

    对象模型比起JavaScript好的不是一点两点,clone关键字真是为原型式编程量身打造的,new就显得不伦不类了,尤其是我从Java开始的。恩,废话就少提,下面我学习Ruby的各个部分。其中Ruby风格这一部分是开放的,因为我...

    Ruby on Rails Web开发之旅.pdf【第一部分】

     3.3.2 与Ruby对象交互  3.3.3 Ruby中的标点  3.4 在Ruby中使用面向对象编程  3.4.1 类和对象  3.4.2 对象层功能  3.4.3 类层功能  3.4.4 继承  3.4.5 返回值  3.5 标准输出  3.6 Ruby核心类  ...

    Ruby on Rails Web开发之旅.pdf【第二部分】

     3.3.2 与Ruby对象交互  3.3.3 Ruby中的标点  3.4 在Ruby中使用面向对象编程  3.4.1 类和对象  3.4.2 对象层功能  3.4.3 类层功能  3.4.4 继承  3.4.5 返回值  3.5 标准输出  3.6 Ruby核心类  ...

    Ruby on Rails Web开发之旅.pdf【第三部分】

     3.3.2 与Ruby对象交互  3.3.3 Ruby中的标点  3.4 在Ruby中使用面向对象编程  3.4.1 类和对象  3.4.2 对象层功能  3.4.3 类层功能  3.4.4 继承  3.4.5 返回值  3.5 标准输出  3.6 Ruby核心类  ...

    Ruby常量查找路径问题深入研究

    Ruby 的常量查找路径问题是一直困扰我的一个问题,在工作中遇到过好几次,一直没有彻底弄清楚到底为什么,最近在读一本书《Ruby 元编程》,对 Ruby 对象模型有了更深入的认识,另外读了一篇 blog《Everything you ...

    编程新手真言......

    8.2 编程能力,代码控制能力,复用与接口,轮子发明与使用 170 8.3 OO,模板,设计模式与设计 171 8.4 设计能力和程序员能力模型 172 8.4 自上而下设计和自下而上设计 173 8.5 大中型软件和复用与逻辑达成 177 8.6 ...

    跨越边界:Rails迁移

    目前,持久性框架使用两种方法中的一种:映射或包装 。要有效地管理涉及持久性域模型的应用程序变化,必须协调数据、模式和模型...这篇文章研究的Rails模式迁移是一种把每个数据库的模式变化与基本对象模型分离的思想。

    几个加速Ruby on Rails的编程技巧

    Ruby 语言常以其灵活性为人所称道。正如 Dick Sites 所言,您可以 “为了编程而编程”。...例如,Ruby on Rails 基于模型-视图-控制器(Model-View-Controller,MVC)模式,这意味着大多数 Rails 应用程序都

    精通qt4编程(源代码)

    较深入地分析了Qt对象模型的一些基本知识,涉及信号和槽机制、Qt元对象系统、属性系统和对象树机制,以及部件类型和部件的几何布局等内容。 35 \ 第4章 程序主窗口—— QMainWindow 卢传富 Qt应用程序的主窗口是由多...

    借助RubyGnome2库进行GTK下的Ruby GUI编程的基本方法

    前言 随着RubyGnome2库越来越完善,以及ruby1.9的性能提升,用Ruby编写GUI程序渐渐从我的业余爱好转为我工作的一个重要部分。   用Ruby写程序确实很有乐趣,它可以让你的想法...它对GTK+的对象模型仔细地用Ruby的方

    精通Qt4编程(第二版)源代码

    较深入地分析了Qt对象模型的一些基本知识,涉及信号和槽机制、Qt元对象系统、属性系统和对象树机制,以及部件类型和部件的几何布局等内容。 35 \ 第4章 程序主窗口—— QMainWindow 卢传富 Qt应用程序的主窗口是由...

    领域驱动设计和实践.docx

    随着编程语言和技术的发展,各种语言特性层出不穷,面向对象是大部分语言的一个基本特性,像C++、Java、C#这样的静态语言,Ruby、Python这样的动态语言都是面向对象的语言。 但是面向对象语言并不是银弹,如果开发...

    在Ruby on Rails中优化ActiveRecord的方法

    Ruby on Rails 编程常常会将您宠坏。这一不断发展的框架会让您从其他框架的沉闷乏味中解脱出来。...将对象模型设计建立于数据库结构之上的那些框架称为包装框架。与大多数包装框架不同,Rails 能通过查询数据

    crash-into-ruby:RubyConf Australia 2015 Ruby Workshop

    它将带您从基本的 Ruby 编码到对象模型的秘密,再到高级元编程技术。 无论您是 Java 开发人员、Python 大师还是 JavaScript 向导,本次研讨会都将向您展示 Ruby 的重要之处、人们为何如此喜爱它,以及为什么惯用的 ...

    Umple:面向模型编程的技术-开源

    Umple是面向模型编程的技术。 它将诸如UML关联,属性和状态机之类的抽象添加到诸如Java,C ++,PHP和Ruby之类的面向对象的编程语言中。

    luact:受赛璐oid(ruby)和奥尔良(.NET)启发的编写健壮,可扩展的网络应用程序的框架

    这使熟悉常规编程的人们仅通过编程就可以享受该模型的以下好处,就像他们自然地链接了多个对象一样。 并发编程可以轻松地预测行为:在正常的并发编程中,当处理可随时中断的线程时,很难想象另一个进程将在何处意外...

    curso-rails-feevale:Feevale 的 Ruby on Rails 课程

    #Feevale 的 Ruby on Rails 课程##Ruby历史安装语言(面向对象、块、模块和语法) 宝石交互式控制台 (irb) 元编程##Rails - 概述目前网络开发配置约定MVC ##Rails - 模型(ActiveRecord + ActiveModel) 迁移验证...

Global site tag (gtag.js) - Google Analytics