©
本文档使用
php.cn手册 发布
由Alfred Aho(A)、Peter Weinberger(W)和Brian Kernighan(K)共通创建的一种小型脚本语言。
ml archive (blade/ruby)
进行数据类型变换的方法。如果某数值计算方法从参数那里获得了一个类型不明的实例时, 它会调用coerce
方法来进行数据类型变换。coerce
方法会返回参数中的数值和本身。
Ruby库的数值类型变换顺序为
Fixnum -> Bignum -> Rational -> Float -> Complex
该类可将C中的指针处理成Ruby对象。由C指针、mark函数和free函数构成。如果您想使用C语言来扩充Ruby的功能的话, 就必须掌握该类的使用方法。相反地, 如果您没有这个打算的话, 它也就没什么用了。
defined?
该操作符可以检查某对象(表达式)是否已经被定义。若未被定义就返回nil
,若已被定义,就以字符串形式返回它的种类。虽然defined?
看似一个方法,实际上它是Ruby语法中的操作符, 它不会对参数进行计算。因此下面的表达式
defined? print("abc\n")
不会输出任何内容。
面向对象的编程语言。据说,早先matz在读了该语言作者所撰写的《Object-oriented Software Construction》之后顿觉恍然大悟。但奇怪的是Ruby与Eiffel却并不相似。如果硬要找出雷同之处的话, 可能只有两点: 1.Ruby的块以end
结尾;2.Ruby也有rescue
这个保留字。
end
该保留字表明了块的结束。据统计,大约有33%的人在看到这个end时会联想起Pascal(纯属杜撰)。但它并不和begin连用,因此它可能更接近于Ada或Eiffel。
Ruby之所以不使用C和Perl中的{}
,主要是因为以下原因
避开单句·复句的问题
例如在C语言中, 若想向下例中添加语句时
if (a==b) c();
如果写成这样的话
if (a==b) c(); d();
就会造成难以发现的bug。即使是Pascal也存在这个问题。
回避else
的问题
与上例类似, 如果写出下面这样的语句的话
if (a==b) if (c==d) foo(); else bar();
就会引起混乱。其实它的本意应该是
if (a==b) { if (c==d) foo(); else bar(); }
这个样子。
提高可读性
可能您对此持有异议, 但有的人认为:用end来结束块的做法可以提高程序的可读性。
begin
和case
语法表达上的问题
说句实话,matz曾多次想把end用作变量。甚至探讨过在ruby语法中添加{ }
的问题,但因为无法完美地解决begin
和case
的语法表达的问题,最终不得不放弃这个念头。恐怕这才是最大的理由吧。
ENV
该对象的运作方式与访问环境变量的Hash相同。实际上,它就是添加了特殊方法的Object类的实例。使用该对象来修改环境变量后,其变化将会影响到Ruby的子进程。
常见的问题和解答。Ruby FAQ尚处于不断完善的阶段,问题和解答是随时更新的。
Ruby中没有该语句。这并不是因为“我们觉得不应该使用”goto,而是“实现其功能实在是太麻烦了”。实际上,您可以使用catch/throw
或异常来实现goto的功能。
main
顶层中的self。因为self
是必不可少的,所以它只是表明在顶层中有个Object
类的实例--self而已。另外为了操作Object类,还特别定义了若干特殊方法。
已定义的特殊方法
Ruby的作者,也叫松本 行弘。请参考<URL:http://www.st.rim.or.jp/~fuku/cmail/>,另外,他还是3个孩子的父亲。
就像在冰淇淋中混合多种配料可以做成美味的混合冰淇淋一样,在类中混合插入各种模块就可以添加相应的功能。请参考继承。
matz坚信滥用多重继承会导致继承关系的混乱,因此Ruby中不允许使用多重继承。同时为充分发挥继承功能的优势,Ruby支持两种继承关系:1.使用is-a语句的继承;2.使用Mix-in来共享并继承模块中的功能。
不必多说了罢
Principle of least surprise
Ruby的劲敌。其功力深厚,可谓“千年蛇妖”。但matz认为Python的功能仍不完美,不然就不会创造Ruby了。最要命的是Python限定了名称长度(6个字符)。
Ruby Application Archive(RAA)
Ruby Change Request
Ruby Document
面向对象的脚本语言。Ruby的意思是“紧跟在Perl(pearl是6月的诞生石,Ruby则是7月的诞生石)之后”。Ruby并不是其他单词的缩写。
面向对象的编程语言。其实matz钟爱Sather胜过Eiffel。但Ruby与Sather一点都不像。
self
表示被调的表达式。那为什么把它叫做self
呢?因为如果把方法看作动词的话,那么被调就是该动作的主语,从方法的角度来看,被调当然就是自己了。一般人认为,Ruby对此并未深究,只不过是模仿Smalltalk的做法罢了。
面向对象的编程语言。它奠定了现代面向对象 理论体系的基础。
super
在重定义的方法中调用上级方法。省略参数时,将使用主调方方法的参数来进行调用。
问题:
修改参数中给出的数值后再调用super的话,将会使用原来的值还是修改后的值呢?
def foo(a) print a end def self.foo(a) a=25 super end foo(5) # 5 or 25??
答案:
使用修改后的值(25)
原为Thread of control的缩略语,意指一系列的控制流。在Ruby中,一个程序内可以同时存在若干线程。
undef
将方法设置为未定义状态。继承 和Mix-in的功能都是在类中添加方法,而undef
则可以取消方法。但是,如果取消了类所必需的方法(被其他方法所调用的方法)的话,其后果不堪设想。
方法的执行主体。也就是方法调用表达式的`.
'中的左边部分。在方法内,可以使用self来表示它。另外,您可以使用@变量名
的形式来访问被调的实例变量。
贴在对象上的标签。Ruby的变量包括全局变量、局部变量和实例变量。因为常数的值不能改变,所以不是变量。但它也是一种标签,因此在这一点上它与变量是相同的。
一旦定义了就不能再改变的变量。这个定义本身似乎就有点矛盾。
即指再定义。重新定义超类或include模块中已经定义的方法。使用super即可调用原来的方法。
将数据构造和对其进行操作的过程封装在一起,就形成了抽象数据类型。对抽象数据进行操作时,必须使用封装内的操作才行。其结果是不能从外部直接使用数据构造,同时一旦内部构造发生变化也不会对外界造成不良影响。我们把这个过程叫做封装。
使对象(或“某事物”)变为“就绪”状态。对实例进行初始化操作时,需要重定义Object#initialize方法。类方法Class#new的默认定义就是对新生成的实例执行initialize
方法。传给new
的参数会被原封不动地传给initialize
。另外,若带块调用时,该块会被传给initialize
。
因此,不必对Class#new进行重定义。
根据给出的条目即可查出对应的定义。它是哈希表的别名。面向对象的始作俑者Smalltalk把类似哈希表的数据构造称作“辞典”,所以时至今日仍然有一些人把哈希表称作辞典。
美洲大陆的原住民是Indian而并非Endian,那么这个Endian的词源是什么呢?其实它出自Jonathan Swift写的《格列佛游记》。这本书中的人们因为吃鸡蛋的方法不同而分成两类,从圆头开始吃的叫大Endian,从尖头开始吃的叫小Endian。在计算机业界,该词表示CPU等排列数据的一种方式,据说网络一族的人们喜欢大Endian。请参考字节顺序。
它并不是那种发生在break, next, redo, retry, return等方法的范围内的普通退出,而是一种跨度极大的退出。只要没被捕捉到,它甚至会跳出方法调用的牢笼来引发中断。Ruby的大规模退出包括由异常引起的退出和catch/throw
。
大多数的异常(包括由exit
所引发的SystemExit
在内)都会被rescue 捕捉到。但是若该异常不值得捕捉(例:内存分配失败/解释器的bug)的话,就会放他一马。
在catch/throw
中,通常会从被throw的地方起一直跳转到与throw部分具有相同标签的catch部分为止。
即指调用带块方法。当初为了进行迭代操作而设置了带块方法,现在它仍然常被称作迭带器。虽然可以将那些进行迭代操作的方法叫做迭代器,但如果将所有带块方法的调用过程都看作迭带器的话,势必会引起混乱。
我们把那些可接受代码段(块)的方法叫做带块方法。调用带块方法就是指调用这些带块方法的过程。
在带块方法中使用yield就可以执行块的内容。
当然了,如何处理给出的块,这完全取决于方法。所以,如果硬是把块传给一个不能带块的方法的话,也不会有什么结果,而且也不会发生错误。
指在运行时根据操作对象的数据类型的不同来选择合适的过程(方法)。它可以提高程序的灵活性。它是面向对象的必要条件之一。在Ruby中变量是没有类型的,因此必然可以进行动态绑定。
它是一种特殊的局部变量。Ruby的局部变量的作用域是固定的,因此在编译时就会生成局部变量。动态局部变量则有所不同,每次执行时才会生成变量。在块中首次被赋值的局部变量就是动态局部变量,其作用域仅限于块的内部。这主要是为了让各个Thread都能拥有自己独立的变量而设的。
即指物体。举个例子,“爱”可能不是对象,但“情书”却是对象。甄别某事物是否属于对象,这可能是个哲学问题。或许正因为如此,面向对象也变得扑朔迷离起来。在计算机业界有人认为对象就是指内存中的特定空间。到底何谓对象,还真是个难题。另外,请参考封装和抽象数据类型。
根据对象的不同选择合适的操作。在Ruby中的实现方法是,根据被调的对象的不同来选择不同的方法。
例
obj = "abc" print obj.length, "\n" # => 3 obj = [1,2,3,4] print obj.length, "\n" # => 4
对对象进行的操作。操作对象(被调)以self来表示。在Ruby中,除去内部类的对象以外,通常对象的构造都是动态确定的。某对象的性质由其内部定义的方法所决定。
将内部结构和算法隐藏起来,以确保只有特定的过程(也叫方法)才能直接操作数据,这种隔离方法就叫做封装。请参考抽象数据类型。
在Ruby中,只有方法可以操作实例变量,因此可以说Ruby中的封装是强制性的。
哈希表的别名。因为哈希表可以使用任意的键来引出值,这就是“关联”特性。另外,可以将哈希表看作是使用非数字形式索引的数组,这是它的“数组”特性,因此它也叫做“关联数组”。以前是使用硬件来实现关联数组(也叫关联记忆)的功能的,但是随着计算速度的攀升以及关键算法(叫做“哈希表”,它是现在的哈希表的词源)的成功研发,现在只用软件就可以实现其功能了。
Ruby中的一种从键到值的映像(mapping)。也叫做关联数组或辞典。哈希表之所以得此名,是因为在实现其功能时使用了一种叫做“哈希表”的算法。哈希的意思是“切碎”,是“hashed beef”中的“hash”。
严格地讲,Ruby中没有函数。但那些省略被调的方法调用看来确实很像函数,而且有的方法根本不需要self或实例变量等被调信息,事实上后者已成为函数了。所以有时也就网开一面地把这样的方法叫成函数了。
通常将这种函数(式的方法)的方法可视性设成了private,这样就只能以省略被调的形式来调用它们了。这类方法中比较有代表性的是 模块函数。
父进程传给子进程的值。使用ENV就可以访问环境变量。传给子进程只是环境变量的副本,因此子进程无法通过环境变量来向父进程传递信息。这就好比老子不会听小孩的话一样。
主要依赖于从祖先或亲戚那里继承的功能,而自己只做一些补充性的工作。在现实世界中,这种行为是要遭到唾弃的,但在计算机世界里这却是个很经济的做法。继承也可以指在某类中添加新功能后生成一个新的类。继承可以用is-a的关系来加以诠释。例如,如果您要生成一个“理科学生”类的话,需要首先继承描述一般学生特征的“学生”类,然后再添加“整天忙于应付实验”等特征后即可生成该类。若不存在is-a关系,而只想共享某些特性或功能时,我们推荐您使用Mix-in。
脚本,特指由解释器进行处理的较短的程序。当然了,其中也不乏大作。
脚本语言。
只能在特定范围内使用的变量。该范围就是作用域。Ruby的作用域包括
几种。只有块能访问外侧作用域的局部变量。局部变量的作用域 从该变量首次被赋值的位置起 直到该赋值位置所在的作用域结束为止。这个优先范围是静态决定的,与具体的运行情况无关。
可用来构成循环或打家劫舍。
就是类的方法。可分为两种:第一种是在所有的类的超类Class中定义的,且被所有的类所共享的方法;第二种是各个类所特有的特殊方法。这倒没什么问题。重要的是类方法中的self
指的是类本身,这点需要牢记。
实际的数值就保存在变量之中,这和引用是不同的。目前,Ruby中只有Fixnum、Symbol和nil/true/false是立即值。然而Ruby的某些版本并未将Fixnum算做立即值,这也无关紧要。在理论模型层面上,可以将所有的值都看作是对某对象的引用。
类似于“思维方式”,这个词很难说得清楚。
以对象为中心的理论体系。英语中的"Object-Oriented"是个形容词,可是到了日语中就变成名词了。似乎只要将对象置于思考的中心点就万事大吉了,但也要兼顾一下几点
多态
(或者动态绑定)
有人甚至把它看作是包治百病的“魔法”,但事实上世界并非如此简单。面对对象概念诞生至今已逾20个年头,它已经磨砺成为一把实用的利剑。
以对象作为出发点的系统设计
以对象作为编程的中心。
以对象为根本的系统分析。
在那些函数式的方法中,模块函数既可用作模块的方法,又可用作特殊方法。例如Math模块中的大部分方法都是模块函数。您既可以这样
Math.sqrt(2)
又可以这样
include Math sqrt(2)
来使用它们。
这些内部类被嵌入Ruby解释器内部,其实例的结构与普通对象有所不同。我们不建议您继承内部类。Ruby的内部类如下所示(实际上远不止这些,更多详情请参考内部类/模块/异常类)
将对象依次排列。只要元素是可数的(include了Enumerable
)、且已定义了顺序(定义了<=>)的话,Ruby就可以对这些元素的集合进行排序。这并不仅限于数组,也适用于其他复杂对象的集合。
因为String#chop!, Array#concat这种方法会直接改变被调的状态,因而会产生“破环性的作用”。不过您不必担心,因为它们不会损坏您的计算机。
在程序的各个角落中都可以使用的变量。比较危险,少用为佳。
即指对象。在强调对象归属于某类时,常使用实例这个词。据说有好多人因为不了解对象和实例的关系,因而搞不懂面对对象到底是怎么一回事儿。
对象所特有的变量。Ruby实例变量名前都有一个@
符号,您只能在方法内部使用它。
专属于某特定对象的方法。请参考方法。在下列情况下,其他对象也可以继承该特殊方法。
若在特殊方法中重定义了原先类中的方法时,可以使用super来调用原来的方法。
只对应于某特定对象的假想类。
matz最头疼的就是写文档了。他平时总是说“源代码就是文档。连bug也写得清清楚楚”,当然了谁都不以为然。
开始有10个人,后来越来越少。在计算机业界中,它是表示一种排列数据的形式。据说有一家大的CPU制造商很喜欢小Endian。请参考字节顺序。
遇到非正常情况就会引发异常。发生异常时,只要没使用begin中的rescue
进行捕捉的话,它将跨越方法调用的阻拦,进而中断程序(thread)的运行。有了异常处理功能之后,我们就不必再逐一检查Ruby程序中的每个异常情况了。发生异常的地点信息被保存在$@中,而异常本身的信息被保存在$!中。
即指重定义。
将0x01020304
这4个字节数据按照1,2,3,4
或是4,3,2,1
的顺序排列。前者叫做大Endian,而后者叫做小Endian。人们一直在争论哪种方法更好,但至今尚无定论。