《ruby编程语言》笔记2 对象
ruby是一门非常纯粹的面向对象的语言:所有值都是对象,而且没有基本类型(primitive type)和对象类型的区别,这一点不同于其他语言。在Ruby中,所有对象都继承一个Object类,而且共享那些定义于此类中的方法。
对象引用object references
当我们在ruby中使用对象时,其实是在操作对象的一个引用,而非对象本身。当我们将一个值赋值给一个变量时,我们并没有将一个对象copy到该变量,而是在此变量中存储了一个指向那个对象的引用。下面代码可以说明这点:
s = "Ruby" # Create a String object. Store a reference to it in s.
t = s # Copy the reference to t. s and t both refer to the same object.
t[-1] = "" # Modify the object through the reference in t.
print s # Access the modified object through s. Prints "Rub".
t = "Java" # t now refers to a different object.
print s,t # Prints "RubJava".
When you pass an object to a method in Ruby, it is an object reference that is passed
to the method. It is not the object itself, and it is not a reference to the reference to the
object. Another way to say this is that method arguments are passed by value rather
than by reference, but that the values passed are object references.
Because object references are passed to methods, methods can use those references to
modify the underlying object. These modifications are then visible when the method
returns.
在ruby中,当把一个对象传递给一个方法时,其实传递的是该对象的引用,被传递的既不是对象本身,也不是一个指向该对象的引用的引用。换言之,方法实参时通过”值“而不是”引用“来传递的,只不过这里被传递的值正好 是对象的引用。(这里十分值得注意)
因为对象引用被传递给方法,所以方法可以利用这些引用来修改底层的对象。
Fixnum和symbol实现细节上不是引用,但可以看成”引用“。
Object Class and Object Type对象类和对象类型
There are several ways to determine the class of an object in Ruby. The simplest is
simply to ask for it:
o = "test" # This is a value
o.class # Returns an object representing the String class
If you are interested in the class hierarchy of an object, you can ask any class what its
superclass is:
o.class # String: o is a String object
o.class.superclass # Object: superclass of String is Object
o.class.superclass.superclass # nil: Object has no superclass
In Ruby 1.9, Object is no longer the true root of the class hierarchy:
在ruby1.9中,Object不再是所有类的根类了:
# Ruby 1.9 only
Object.superclass # BasicObject: Object has a superclass in 1.9
BasicObject.superclass # nil: BasicObject has no superclass
检查一个对象所属类的直接方法就是通过直接比较:
o.class==String
instance_of?方法同样可以完成同样的事情,但是更优雅:
o.instance_of? String
Usually when we test the class of an object, we would also like to know if the object is
an instance of any subclass of that class. To test this, use the is_a? method, or its
synonym kind_of?:
通常情况下,我们想要知道对象是类的某个子类的实例,使用is_a?或同义方法kind_of?
x = 1 # This is the value we're working with
x.instance_of? Fixnum # true: is an instance of Fixnum
x.instance_of? Numeric # false: instance_of? doesn't check inheritance
x.is_a? Fixnum # true: x is a Fixnum
x.is_a? Integer # true: x is an Integer
x.is_a? Numeric # true: x is a Numeric
x.is_a? Comparable # true: works with mixin modules, too
x.is_a? Object # true for any value of x
Class类定义了===操作符,可以替换is_a?
The Class class defines the === operator in such a way that it can be used in place of
is_a?:
Numeric === x # true: x is_a Numeric
This idiom is unique to Ruby and is probably less readable than using the more
traditional is_a? method.
在使用ruby编程的时候,我们常常不太在意一个对象所属的类是什么,只想知道是否可以在它身上调用某些 方法。让我们来看看<<这个例子。一般表示追加,如果我们正在编写一个产生文本输出的方法,那么也可以在该方法中使用这个操作符,然后在调用这个方法的时候,使用任何实现了<<操作符的参数。我们并不在意所属的类型,只要能够通过它调用<<操作符即可。我们可以使用respond_to?方法来测试这一点:
o.respond_to? :"<<"
这种做法的缺点在于它仅仅检查了一个方法的名称,而没有检查该方法的参数。比如,Fixnum和Bignum将<<实现为左移位操作符,而且希望其参数为一个数字而不是字符串。当我们使用respond_to?方法来测试时,整数对象看起来是”可追加的“,但是当我们试图在一个字符串后面添加一个整数时,就会产生错误。对于这个问题没有普遍试用的解决办法,但是对于本例中的情况,一个权宜之计是采用is_a?方法显式地将Numeric对象排除在外。
o.respond_to? :"<<" and not o.is_a? Numeric
关于类型和类之间的差别的另一个例子是StringIO类(ruby标准库)。StringIO使得我们可以对字符串对象进行读写。就像他们是IO对象一样,stirngIO魔法了IO的API。
关注类型而不是类,形成了Ruby中一种被称为” duck typing“的编程风格。
对象的相等性Object equality
ruby拥有多的出奇的方法来比较对象的相等性。了解他们的工作机制是非常重要的。这样才能在适当的时候选择正确的方法。
equal?方法
The equal? method is defined by Object to test whether two values refer to exactly the
same object. For any two distinct objects, this method always returns false:
a = "Ruby" # One reference to one String object
b = c = "Ruby" # Two references to another String object
a.equal?(b) # false: a and b are different objects
b.equal?(c) # true: b and c refer to the same object
By convention, subclasses never override the equal? method.
Another way to determine if two objects are, in fact, the same object is to check their
object_id:
a.object_id == b.object_id # Works like a.equal?(b)
==操作符
在Object类里,他是equal?方法的同义词。用于比较两个对象的引用是否是同样的。大多数类都重定义了这个操作符,使不同的实例之间也可以进行相等性测试。
a = "Ruby" # One String object
b = "Ruby" # A different String object with the same content
a.equal?(b) # false: a and b do not refer to the same object
a == b # true: but these two distinct objects have equal values
针对java程序员的说明:
If you are a Java programmer, you are used to using the == operator to test if two objects
are the same object, and you are used to using the equals method to test whether two
distinct objects have the same value. Ruby’s convention is just about the opposite of
Java’s.
Numeric类在它们的==操作符里将进行简单的类型转换,因此(比如)fixnum 1和float 1.0通过==比较的结果是相等的。
irb(main):113:0> 1==1.0
=> true
诸如String和Array等类的==操作符,通常要求他的两个操作符属于同一个类。如果右操作数定义了一个to_str或to_ary转换方法,那么原先的==操作符就会调用右侧操作数定义的操作符==,以此来判定是否相等。
!=(不等于)在ruby中用于测试不等性。当ruby见到!=时,他会简单的使用==操作符并且反转结果。这意味着一个类只需定义==操作符来实现其相等性的含义。ruby会为你免费提供!=。但是ruby1.9中,类也可以显示定义他们自己的操作符。
eql?方法
Object将eql?方法定义成equal?方法的同义词,那些重定义了eql?方法的类通常将其作为一个严格版的==操作符,即不予许进行类型转换,比如:
1==1.0 # true:fixnum and float objects an be ==
1.eql?(1.0) #false: but they are never eql?
===操作符
===通常称为”条件相等性(case equality)"操作符,用于测试一个case语句的目标值是否和某个when从句相匹配。
Object类定义了一个默认的===操作符,他会调用==操作符,因此,对于许多类来说,条件相等性和==相等性是一样的。但是某些关键的类重新定义了===,使其不仅仅是一个成员关系或匹配操作符:
Range类定义了===,用于测试一个值是否位于某个范围内
Regexp定义了===,用于测试一个字符串是否与某个正则匹配
Class类定义了===,用于测试一个对象是否是该类的一个实例
在ruby1.9中,Symbol类定义了===,当其左右2个操作数是同一个符号对象时,或者当其右侧操作数是一个持有和左侧符号对象相同文本的字符串时,该操作符返回true。举例如下:
(1..10) === 5 # true: 5 is in the range 1..10
/\d+/ === "123" # true: the string matches the regular expression
String === "s" # true: "s" is an instance of the class String
:s === "s" # true in Ruby 1.9
像这样显式地使用===操作符并不多见,更为常见的是在一个case语句里隐式地使用它。
对象的顺序object orders
在ruby中,类通过实现<=>操作符定义其顺序性。左边小于右边,返回-1,反之返回1.相等返回0。如果2个操作数之间的比较操作没有意义(如:假设右侧操作数属于另一个类)。那么该操作符返回nil。
1 <=> 5 # -1
5 <=> 5 # 0
9 <=> 5 # 1
"1" <=> 5 # nil: integers and strings are not comparable
只要定义了<=>操作符就可以对值进行比较,但是这并不直观,所以,典型情况下,那些定义了<=>操作符的类还会将Comparable模块作为一个mixin包含进来。
对象的转换 object conversion
许多ruby类定义了一些方法,他们可以返回对象的一种表示形式(representation),而这种形式本身却是另一个类的值。比如用于获取一个对象的Stirng表示形式的to_s方法。也许是最常被实现和最有名的了。
Explicit conversions 显示转换
Classes define explicit conversion methods for use by application code that needs to
convert a value to another representation. The most common methods in this category
are to_s, to_i, to_f, and to_a to convert to String, Integer, Float, and Array,
respectively.
Built-in methods do not typically invoke these methods for you. If you invoke a method
that expects a String and pass an object of some other kind, that method is not expected
to convert the argument with to_s. (Values interpolated into double-quoted strings,
however, are automatically converted with to_s.)
内建的方法通常不会自动调用。如果你调用一个参数为String的方法,却传递一个其他类型的对象给它,该方法是不会主动调用参数的to_s方法来进行转换的。(然后,对于那些内插在双引号里面的字符串的值,ruby会利用to_s来自动转换)
(我能说ruby是强类型的吗?)
3.8.7.2 Implicit conversions 隐式转换
Sometimes a class has strong characteristics of some other class. The Ruby Exception
class represents an error or unexpected condition in a program and encapsulates an
error message. In Ruby 1.8, Exception objects are not merely convertible to strings; they
are string-like objects and can be treated as if they were strings in many contexts.* For
example:
# Ruby 1.8 only (1.9运行不了)
e = Exception.new("not really an exception")
msg = "Error: " + e # String concatenation with an Exception
Because Exception objects are string-like, they can be used with the string concatenation
operator. This does not work with most other Ruby classes. The reason that
Exception objects can behave like String objects is that, in Ruby 1.8, Exception implements
the implicit conversion method to_str, and the + operator defined by String
invokes this method on its righthand operand.
Other implicit conversion methods are to_int for objects that want to be integer-like,
to_ary for objects that want to be array-like, and to_hash for objects that want to be
hash-like. Unfortunately, the circumstances under which these implicit conversion
methods are called are not well documented. Among the built-in classes, these implicit
conversion methods are not commonly implemented, either.
对于在何种情形下这些隐士转换方法会被调用,ruby没有很好的文档化。此外,在内建类里,这些隐士转换方法也没用被普遍地实现。
转换函数
Kernel模块定义了4个转换方法,作为全局转换函数。这些函数--Array、float、Integer即String。具有和他们将要转换的类相同的名字,
Array函数试图调用to_ary方法来将其实参转换为一个数组。如果没有定义to_ary方法,或者该方法返回nil,那么Array函数就会试着调用to_a方法。如果没有定义to_a方法,或者该方法返回nil,那么Array函数就会简单地返回一个新数组,并且将其实参作为该数组的一个元素。
《ruby编程语言》笔记2 对象的更多相关文章
- Ruby零碎笔记
Ruby零碎笔记 飞机上阅读pdf的笔记,因为不联网,内容不多而且比较零散,以tips的形式记录 tips 查看当前作用域的变量 puts local_variables ruby中方法传递参数时,括 ...
- Ruby入门笔记
Ruby入门笔记 一切皆为对象 “Hello”.length 方法 定义:def开头 end结尾 命名一般采用下划线分隔单词
- Ruby学习笔记(二)
1.block 代码块 do...end 或 {} 构成一个代码块,就像常见的 .each后面跟的代码块. my_nums = [1,2,3] my_double_nums = my_nums.col ...
- Ruby中如何复制对象 (deep clone)(转载)
Ruby中如何复制对象 (deep clone) 用Ruby复制一个对象(object)也许没有你想像的那么容易. 今天我google了半天, 做个总结吧. 先从最简单的开始, b = a 是复制吗? ...
- Ruby学习笔记4: 动态web app的建立
Ruby学习笔记4: 动态web app的建立 We will first build the Categories page. This page contains topics like Art, ...
- ruby学习笔记(1)-puts,p,print的区别
ruby学习笔记-puts,p,print的区别 共同点:都是用来屏幕输出的. 不同点:puts 输出内容后,会自动换行(如果内容参数为空,则仅输出一个换行符号):另外如果内容参数中有转义符,输出时将 ...
- atitit.编程语言 类与对象的 扩展机制.doc
atitit.编程语言 类与对象的 扩展机制.doc 1.1. Java 下一代: 没有继承性的扩展1 1.2. 继承1 1.3. 使用cglib动态为Java类添加方法1 1.4. 工具类 1 1. ...
- Python学习笔记_Python对象
Python学习笔记_Python对象 Python对象 标准类型 其它内建类型 类型对象和type类型对象 Python的Null对象None 标准类型操作符 对象值的比較 对象身份比較 布尔类型 ...
- ruby编程语言-学习笔记4(第4章 表达式和操作符)
4.6.9 范围 Flip-Flops: ..和... ..和... 操作符不是基于方法的,无法重定义.(优先级比较低) x+1 .. x*x #可以认为是x+1 至 x*x 的范围 因为操作 ...
随机推荐
- 不同浏览器应用scrollTop属性
window.onscroll = _onScroll;function _onScroll(){ var aside = document.getElementsByClassName('aside ...
- 在Linux下开始C语言的学习
为什么要在linux下学习C语言? linux下可以体验到最纯粹的C语言编程,可以抛出其他IDE的影响 环境配置简单,一条命令就足够.甚至对于大多数linux发行版本,都已经不需要配置C语言的环境 查 ...
- ubuntu 安装 fcitx
安装fcitx (1)添加ppa源 sudo add-apt-repository ppa:fcitx-team/nightly 或 sudo add-apt-repository ppa:fcitx ...
- 零基础Visual Fox Pro 6.0自学笔记(VFP6.0图文教程)
序:有个哥们读大一,学的金融,由于考试需要去学VFP.拜托我帮忙找教程,发觉网上没有合适的,教学视频多半要收费,优秀文档很少.微软官方也不重视VFP了,真可惜.遂生出写一个入门教程的想法.图文并茂的可 ...
- iOS10---新特性以及适配点(转)
iOS 10 新特性以及适配点 SiriKit 所有第三方应用都可以用Siri,支持音频.视频.消息发送接收.搜索照片.预订行程.管理锻炼等 Proactive Suggestions 系统预先建议 ...
- c常用字符串函数
获取字符串长度 : size_t strlen(const char *str); 字符串拷贝函数: 把src中内容拷贝到dest中,它会覆盖原来的内容,它会把src中的\0,没有覆盖内容不变 如果s ...
- C#基础整理
元旦整理书架发现一本小册子——<C#精髓>中国出版社2001年出版的,粗略翻了下关于C#的知识点挺全的虽然内容谈得很浅也有很多过时的内容(话说这本书是我在旧书店花5块钱淘的)我保留原有章节 ...
- ECMAScript 6 中的一些新特性
1.箭头函数,直接写出来v =>看不出来什么,但是跟传统写法一比较,很直观地就能看出v =>是代替了匿名函数 function(v)的写法,{}与逻辑照旧,但是要注意,=与>之间不能 ...
- 【制作镜像】virsh
首先进入到图形界面 常用virsh指令: 1)virsh list 列出当前虚拟机列表,不包括未启动的 2)virsh list --all 列出所有虚拟机,包括所有已经定义的虚拟机 3)virsh ...
- 【原创】Android开发之ADB及ADB SHELl命令的应用
adb的全称为Android Debug Bridge,就是起到调试桥的作用.通过adb我们可以在Eclipse中方面通过DDMS来调试Android程序,说白了就是debug工具.adb的工作方式比 ...