开篇
空即是色,色即是空。
空空色色,色色空空,在Ruby语言中,万物皆为对象。
Ruby是一个面向对象的语言(Object Oriented Language),面向对象的概念比其他语言要贯彻的坚定很多。
Ruby中不存在Java中原始类型数据和对象类型数据之分。大部分Ruby中的的东东都是对象。
所以,想要掌握Ruby和Ruby的元编程,对象就是第一门必修功课。本回就着重研究一下Ruby中的对象.
Ruby中的对象
如果你从其他面向对象的语言转来,一提到得到一个对象你可能会想到建立一个类,然后建立这个类的实例出来产生一个对象。
在Ruby中这完全是可以的,不过这种先建立类才能获得对象的过程,听起来更像是面向类的设计,而不是面向对象的设计。关于类的一些东西放到下回再说。
在Ruby中,不存在原始类型的概念,1, 0.3, true/false 甚至 nil都是对象。比如,你可以在irb中尝试下面的代码:
>> 1.methods => ["%", "odd?", "inspect", "prec_i", "<<", "tap", "div", "&", "clone", ">>", "public_methods", "__send__", "instance_variable_defined?", "equal?", "freeze", "to_sym", "*", "ord", "lcm", "+", "extend", "next", "power!", "send", "round", "methods", <…more methods…> "is_a?", "ceil", "[]"] >> 1.class => Fixnum
你可以在irb中尝试一下其他数据类型,看看他们的方法和类等等信息。
不只是各种数据类型,方法在Ruby中也是对象, 比如下列例子:
>> one_plus = 1.method(:+) => #<Method: Fixnum#+> >> one_plus.class => Method >> one_plus.call(2) => 3
有意思的是,方法对象也是有方法的:
>> one_plus.arity() => 1
对象到底是什么?
到底什么是对象呢?
简单的说,**对象就是 状态 + 行为**
状态 就是表明当前对象所拥有的属性,每个同类的对象可能有不同的状态,这些状态保存在实例变量里面(Instance Variable).
对象的实例变量可以由instance_variable_set/instance_variable_get来设定/读取:
>> 1.instance_variable_set(:@my_var, "world") => "world" >> 1.instance_variable_get(:@my_var) => "world"
行为 行为就是作用在对象上的动作,就是我们常说的方法。Ruby方法的调用,类似于smalltalk或者Objectiv-C,采用消息模式。调用方法相当于对这个对象发送了一个消息。所以对方法的调用也可以这样:
在Ruby中,状态,也就是实例变量是保存在对象里的,而行为或方法则是存在于对象的类或者mixin的module里面。
在静态语言中,编译时就会确定所调用的方法是否存在,不存在会产生编译错误。
Ruby中,当我们在方法调用的运行时,对象会查找他隶属的类,module,父类等,来找到相对应的方法。
Singleton/Meta/Anonymous/Ghost/Shadow Class
1.Singleton Class: 单例类
2.Meta Class:元类
3.Anonymous Class: 匿名类
4.Ghost Class:鬼类
5.Shadow Class: 影子类
上面的这些东东其实说的都是一个东西,我喜欢叫它 影子类。
Ruby中每一个对象都一个一个影子类,这个影子类存在于对象跟它所属的类之间:
对象("obj1") -> 影子类 -> 对象所属的类(String)
当一个对象的方法被调用时,首先查找的是影子类,之后才是它所属的类。
上面讲到实例变量存在于对象内,方法存在于对象的类中。
影子类上的方法,就是只有这一个对象拥有的方法。这个方法通常叫做单例方法(Singleton Method)。
这样的方法只存在于这个对象上,同一个类的其他对象没有这个方法,因为他们的影子类不同,其他对象的影子类上没有这个方法。
>> a = "obj1" => "obj1" >> def a.hello >> puts "hello world" >> end => nil >> a.hello hello world => nil >> b = "obj2" => "obj2" >> b.hello NoMethodError: undefined method `hello' for "obj2":String from (irb):49 >> a.singleton_methods => ["hello"] >> b.singleton_methods => []
Self
Ruby里面一切都是对象,self也是对象,确切地说是当前对象的引用。
前文说Ruby的方法调用是消息模式,比如obj.method, 消息的接受者是.之前的对象,.之后的是方法及参数。
如果对象和.没有出现的话,消息会被默认送到self对象。除了作为方法的默认接受者,self也是实例变量的解析对象。
self在ruby一开始的时候,被设定为一个叫做main的对象,再irb里面可以看到:
>> m = self => main
>> self = "obj" SyntaxError: compile error (irb):77: Can't change the value of self self = "obj" ^
当我们用obj.method调用方法时,接下来的时间代码的执行就会到相应的方法里,运行的上下文切换到那个对象,self自然也变成了那个对象。用def定义单例方法时,道理也是相通的。 下面的例子可以说明这个self切换的情况。
>> a = "obj" => "obj" >> def a.hello_self >> puts "hello #{self}" >> end >> m = self => main >> a.hello_self hello obj
对象的复制
前文说对象的存在包括两部分,一是状态/实例变量,另一个是行为,本回专注讲了单例方法和影子类。
Ruby中对象的复制也有两种模式,一个是只复制当前的状态/实例变量 dup。另外一种是连同影子类和引用的对象一起复制,从而把单例方法也复制一份。
>> a = "obj" >> def a.hello_self >> puts "hello #{self}" >> end >> b = a.dup => "obj" >> b.hello_self NoMethodError: undefined method `hello_self' for "obj":String from (irb):90 >> b = a.clone => "obj" >> b.hello_self hello obj
你可以建立一个对象,生成默认的实例变量,把行为作为单例方法定以在这个对象的影子类上,然后用clone生成千千万万个实例。当然这样比较麻烦,但却是可行的途径之一。
其他Object API
对象还有很多其他的功能,比如可以freeze,另外dup跟clone也有一些其他的引用上面的区别,dup只复制引用,clone会吧引用的对象也复制。
这些都可以在Object类(Ruby所有对象的父类)API上找到,可以查看apidock.com的文档
例如关于dup
.dup() produces a shallow copy of obj—the instance variables of obj are copied, but not the objects they reference. dup copies the tainted state of obj. See also the discussion under Object#clone. In general, clone and dup may have different semantics in descendant classes. While clone is used to duplicate an object, including its internal state, dup typically uses the class of the descendant object to create the new instance.
本回完
本回讲了些对象相关的东西,有的很基础,有的是Ruby自身的一些特性。
其中Ruby对象模型中最具特色的两个特性就是影子类/单例方法和self,最好能深入理解这两个概念。
且听下回分解
下回注重一些关于类的故事。
2.4. 万物皆对象 2.4.1. 模块导入的搜索路径 2.4.2. 何谓对象? 如果您没在意, 我刚才的意思是 Python 函数有属性, 并且这些属性在运行时是可用的。 在 Python 中, 函数同其它东西一样也是对象。 打开您习惯使用的 Python IDE 执行如下的操作: 例 2.3. 访问 buildConnectionString 函数的 doc string >>> import
本文向大家介绍Ruby元编程小结,包括了Ruby元编程小结的使用技巧和注意事项,需要的朋友参考一下 今天被问到此类问题,以前总是觉得这个是比较宽泛的一个概念,自己即使是用过这些特性,但却一直不知道这叫“元编程” 直到今天被人问起的时候,方才顿悟一些,随后便在网上和自己的平实用的一些元编程做个小总结。 原来所谓的Ruby中的元编程,是可以在运行时动态的操作语言结构(如类、模块、实例变量等)的技术。你
本系列翻译自 Ruby Metaprogramming 站点上的课程笔记,并加入了我(DeathKing)的一些个人演绎、资料补充等。希望对大家有所帮助。
本文向大家介绍Ruby元编程技术详解(Ruby Metaprogramming techniques),包括了Ruby元编程技术详解(Ruby Metaprogramming techniques)的使用技巧和注意事项,需要的朋友参考一下 我最近考虑了很多元编程(Metaprogramming)的问题,并希望看到更多这方面技术的例子和讲解。无论好坏,元编程已经进入Ruby社区,并成为完成各种任务和
本文向大家介绍Ruby面向对象编程详解,包括了Ruby面向对象编程详解的使用技巧和注意事项,需要的朋友参考一下 Ruby是纯面向对象的语言,所有项目似乎要Ruby中为一个对象。Ruby中的每个值是一个对象,即使是最原始的东西:字符串,数字甚至true和false。即使是一个类本身是一个对象,它是Class类的一个实例。本章将通过所有功能涉及到Ruby的面向对象。 类是用来指定对象的形式,它结合了数
主要内容:什么是 Sockets,简单的客户端,实例,简单的服务,实例,多客户端TCP服务,实例,微小的Web浏览器,实例,实例Ruby提供了两个级别访问网络的服务,在底层你可以访问操作系统,它可以让你实现客户端和服务器为面向连接和无连接协议的基本套接字支持。 Ruby 统一支持应用程序的网络协议,如FTP、HTTP等。 不管是高层的还是底层的。ruby提供了一些基本类,让你可以使用TCP,UDP,SOCKS等很多协议交互,而不必拘泥在网络层。这些类也提供了辅助类,让你可以轻松的对服务器进行读写