ruby语法基础教程_第1页
ruby语法基础教程_第2页
ruby语法基础教程_第3页
ruby语法基础教程_第4页
ruby语法基础教程_第5页
已阅读5页,还剩83页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、Grant Renhyqryq2006年11月24日 前 言 目 录Ruby语言1Grant Ren1第一部分 Ruby语言基础8第一章 Ruby语言概述8§1.1 Ruby的历史8§1.2 Ruby名字的由来8§1.3 Ruby的特点8§1.4 Ruby和Python的比较9第二章 Ruby编程环境9§2.1 Ruby的安装9§2.1.1 在Windows 95/98/Me/XP上安装Ruby9§2.1.2 在Linux上安装Ruby10§2.2 运行Ruby10§2.2.1 使用Ruby10§

2、;2.2.2 使用FreeRIDE和SciTE11§2.2.3 使用fxri13§2.3 Ruby-irb14§2.4 Ruby-ri15§2.5 RubyGems15第三章类与对象17§3.1 类的定义17§3.2 对象,属性和方法18§3.3 继承20§3.4 特殊方法与特殊类21§3.5 类变量与类方法23§3.4 存取控制23§3.6 元类25§3.7 Ruby的动态性26§3.8 变量26§3.8.1 局部变量27§3.8.2 实例变量

3、27§3.8.3 类变量27§3.8.4 全局变量28§3.8.5 常量28§3.8 与定义有关的操作29§3.8.1 alias29§3.8.2 undef30§3.8.3 defined?31第四章基本类型33§4.1 Array33§4.2 Hash34§4.3 Number34§4.4 String35§4.5 Range36§4.6 Symbol37§4.7 正则表达式37第五章代码块和迭代器38§5.1 代码块(Block)38

4、67;5.1.1 什么是代码块38§5.1.2 代码块与对象39§5.2 迭代器(Iterator)40§5.2.1 什么是迭代器40§5.2.2 使用迭代器40§5.2.3 yield41§5.2.4 编写自己的迭代器42第六章表达式42§6.1 运算符43§6.2 命令替换44§6.3 赋值运算符44§6.4 并行赋值46§6.5 嵌套赋值47§6.6 其他赋值47§6.7 条件运算47§6.8 case表达式48§6.9 循环49§

5、;6.9.1 Loop49§6.9.2 While50§6.9.3 Until50§6.9.4 Iterator50§6.9.5 For.In51§6.9.6 Break,Redo,Next51§6.9.7 Retry53第七章方法54§7.1 运算符重定义55§7.2 变长参数56§7.3 块调用56§7.4 方法返回值57第八章模块59§8.1 名字空间59§8.2 mixin59§8.3 使用mixin60§8.3.1 Comparable60

6、67;8.3.2 Enumerable61§8.3.3 Singleton62§8.4 Require, load和include62第九章异常64§9.1 异常处理64§9.2 定义异常类68§9.3 catch和throw68第十章多任务处理69§10.1 多线程处理69§10.1.1 线程创建69§10.1.2 线程操作70§10.1.3 线程和异常71§10.1.4 线程调度73§10.1.5 线程同步73§10.2 多进程处理79§10.2.1 进程创建7

7、9第十一章基本I/O操作80§11.1 使用Kernel模块处理I/O操作80§11.2文件处理80§11.3 StringIO81§11.4 Socket82第十二章反射和对象空间82§12.1 ObjectSpace模块82§12.2 察看类和对象的状态83§12.3 动态方法调用86§12.3.1 使用send方法86§12.3.2 使用Method类和UnboundMethod类86§12.3.3 使用eval方法88§12.3.4 性能88§12.4 Hook和回调

8、方法89§12.4.1 什么是Hook89§12.4.2 Ruby中的Hook89§11.4.2 回调方法90§12.5 跟踪程序的运行90§12.5.1 set_trace_func90§12.5.2 trace_var91§12.5.3 caller91§12.5.3 _FILE_,_LINE_和SCRIPT_LINES_92第十三章序列化和YAML92§13.1 序列化的概念92§13.2 使用序列化93§13.2.1 二进制数据保存93§13.2.2 YAML数据保存

9、93§13.3 定制序列化94§13.3.1 二进制数据保存94§13.3.2 YAML数据保存95§13.3 YAML95§13.3.1 集合类型96§13.3.2 单行集合类型99§13.3.3 基本类型99§13.3.4 块99§13.3.5 别名和锚(Aliases and Anchors)99§13.3.6 文档99§13.3.7 Ruby中YAML的使用99第十四章安全控制100§14.1 0级101§14.1 1级101§14.2 2级101

10、§14.3 3级101§14.4 4级101第十五章单元测试101§15.1 什么是单元测试101§15.2 Ruby单元测试框架101第二部分内置类与模块101第一章内置类102§1.1 Array102§1.2 Bignum102§1.3 Binding102§1.4 Class102§1.5 Continuation102§1.6 Dir104§1.7 Exception104§1.8 FalseClass104§1.9 File104§1.10 F

11、ile:Stat104§1.11 Fixnum104§1.12 Float104§1.13 Hash104§1.14 Integer104§1.15 IO104§1.16 MatchData104§1.17 Method104§1.18 Module104§1.19 NilClass104§1.20 Numeric104§1.21 Object104§1.22 Proc105§1.23 Process:Status105§1.24 Range105

12、7;1.25 Regexp105§1.26 String105§1.27 Struct105§1.28 Struct:Tms105§1.29 Symbol105§1.30 Thread105§1.31 ThreadGroup105§1.32 Time105§1.33 TrueClass105§1.34 UnboundMethod105第二章内置模块106§2.1 Comparable106§2.2 Enumerable106§2.3 Error106§2.4 Fil

13、eTest106§2.5 GC106§2.6 Kernel106§2.7 Marshal106§2.8 Math106§2.9 ObjectSpace106§2.10 Process106§2.11 Process:GID106§2.12 Process:Sys106§2.13 Process:UID106§2.14 Signal106第三部分 Ruby语言总结107附录110§1 术语对照110第一部分 Ruby语言基础第一章 Ruby语言概述§1.1Ruby的历史Ruby

14、语言的发明人是日本人松本行弘(Matsumoto Yukihiro),大家亲切的称呼他"Matz"。可能会出乎大家的意料,Ruby并不是一种近年来才诞生的语言,它的历史可以追溯到1993年,Ruby之父Matz开始对脚本语言感兴趣。在通过一些分析和思考之后,Matz认为脚本语言是可以变得很强大和灵活的,于是他准备把脚本语言作为他的发展方向。 和很多人一样,Matz是一个面向对象程序设计的fans,自然而然他想研究一种支持面向对象程序设计的脚本语言。随后的一段时间,他到网络上搜集了一些相关的资料,并且发现了Perl 5,当时Perl 5还没有发布。通过一段时间了解后,Matz

15、.发现Perl 5这并不是他想的东西,所以他放弃了把Perl当作一个面向对象的脚本语言使用的念头。随后Matz转向了Python,Python是一个解释型的、面向对象语言,但是Matz发现Python并不能完全算作“面向对象”语言。Matz认为Python是面向对象和过程化程序设计语言(Procedural Programming Language)的混合产物。Matz希望找到的是一种比Perl更强大、比Python更面向对象的语言,但是很遗憾, 这样的语言当时在地球上并不存在。于是Matz打算自己设计一个全新的编程语言。1993年2月24日是一个值得纪念的日子,在这一天Ruby诞生了。 19

16、95年12月Matz推出了Ruby的第一个版本Ruby 0.95。 在1996年以前,都是Matz.一个人在开发进行Ruby的开发。后来随着Ruby社区的渐渐形成,很多社区成员给了Matz许多有意义的帮助,包括提交bug和patch等。现在,Ruby像其他开源项目一样,有自己的开发团队,任何有能力的个人或团体都可以参与Ruby的开发与进化。§1.2 Ruby名字的由来首先明确一点,Ruby并不是其他单词的缩写。受Perl的影响,Matz也想用一种宝石来命名他的新语言,他使用了他的一位同事的生肖石红宝石。后来,Matz意识到Ruby这个名字十分恰当,首先,在生肖石中,Pearl代表六月

17、,而Ruby代表七月。在字体大小上,Pearl大小是5pt, ruby的大小是5.5pt。所以Ruby这个名字对于一种Perl的后续语言十分合适。§1.3 Ruby的特点Ruby是一种功能强大的面向对象的脚本语言,可以使用它方便快捷地进行面向对象程序设计。与Perl类似,而且Ruby具有强大的文本处理功能,使文本处理变得简单。此外还可以方便地使用C语言来扩展Ruby的功能。若您曾经“想要一种简单的面向对象的语言”,或者认为“Perl的功能虽然好用,但它的语法真让人受不了”,又或者觉得“LISP系列语言的思想不错,但到处都是括号真让人讨厌,最起码算式应该按照通常的样式书写”。那么,Ru

18、by或许能让您满意。归纳起来,Ruby有以下优点:l 解释型执行,方便快捷Ruby是解释型语言,其程序无需编译即可执行。l 语法简单、优雅语法比较简单,类似Algol系语法。l 完全面向对象Ruby从一开始就被设计成纯粹的面向对象语言,因此所有东西都是对象,例如整数等基本数据类型。l 内置正则式引擎,适合文本处理Ruby支持功能强大的字符串操作和正则表达式检索功能,可以方便的对字符串进行处理。l 自动垃圾收集具有垃圾回收(Garbage Collect,GC)功能,能自动回收不再使用的对象。不需要用户对内存进行管理。l 跨平台和高度可移植性Ruby支持多种平台,在Windows, Unix,

19、Linux, MacOS上都可以运行。Ruby程序的可移植性非常好,绝大多数程序可以不加修改的在各种平台上加以运行。l 有优雅、完善的异常处理机制Ruby提供了一整套异常处理机制,可以方便优雅地处理代码处理出错的情况。l 拥有很多高级特性Ruby拥有很多高级特性,例如操作符重载、Mix-ins、特殊方法等等,是用这些特性可以方便地完成各种强大的功能。同时,由于是解释型语言,Ruby也有下列缺点:l 解释型语言,所以速度较慢l 静态检查比较少§1.4Ruby和Python的比较Python是Ruby的劲敌。其功力深厚,可谓“千年蛇妖”。但matz认为Python的功能仍不完美,不然就不

20、会创造Ruby了。第二章 Ruby编程环境§2.1 Ruby的安装Ruby支持多种平台,包括Windows、Linux、各种类UNIX、MacOS X等。§2.1.1在Windows 95/98/Me/XP上安装Ruby对于使用Windows平台的用户,安装Ruby是相当简单直接的事情。最方便的方法是使用“One-Click Ruby Installer”。不知你有没有听说过SourceForge?SourceForge 是全球最大的开放源代码软件开发平台和仓库。它集成了很多开放源代码应用程序,为软件开发提供了整套生命周期服务。在Ruby世界,也有一个类似的网站,那就是Ru

21、byforge。“One-Click Ruby Installer”是Rubyforge上的一个开源项目,也是Rubyforge上下载量最大的项目之一。这个项目将Ruby语言核心和一系列常用扩展集成到了一起,还包含支持Ruby的免费的IDE工具FreeRIDE和SciTE,除了这些之外还包括帮助文档,示例代码,RubyGems包管理器,Fox GUI库,fxri(Interactive RubyHelp& Console)等。和正如它名字所示,使用它,Ruby安装变得前所未见的容易。你可以在下面的地址下载到它的最新版本:/projects/ruby

22、installer/§2.1.2在Linux上安装Ruby在linux下Ruby的安装要稍微复杂一些,推荐使用源码编译的方式安装,这样可以保证安装的是最新版本。首先到ruby主站/en/下载源代码,下载完毕后解压到目录,然后使用以下命令:./configure./make; make install执行上面的命令需要root权限,默认安装到/usr/local下。你也可以使用“./configure -prefix=自定义路径”来指定安装目录。windows上的ruby one-click installer默认安装了RubyGems,但

23、在Linux下我们需要手动安装RubyGems。RubyGems是一个Ruby的包管理器,我们后边会讲到它。首先从Rubyforge下载RubyGems的最近版本,地址如下:/projects/rubygems/解压RubyGems以后到相应目录下输入ruby setup.rb,屏幕上打印一些日志以后会告诉你安装成功,执行gem -v可以查看gem安装版本号。§2.2运行Ruby下面,我们将以Windows平台下的Ruby环境举例如何运行Ruby。§2.2.1使用Ruby将“Hello World”作为学习计算机语言第一个学写的程序,现

24、在已经成为一种传统。该程序最早出现在由Brian Kernighan和Dennis Ritchie写的经典计算机程序设计教程The C Programming Language。我们来看看Ruby世界的“Hello World”:在Windows中,打开命令行提示符窗口,在提示符上输入“Ruby”并回车,Ruby解释器就会运行并等候输入程序。Ruby可执行文件应该包含在系统搜索路径内。输入下面的程序:print "Hello World!"然后按Ctrl+D再按回车键,你就会看到Ruby执行程序的输出结果:你也可以先将代码保存为文件,然后使用再Ruby解释器执行:§

25、;2.2.2 使用FreeRIDE和SciTEFreeRIDE是一个支持Ruby语言的免费IDE环境。FreeRIDE本身就是使用Ruby语言开发,它也是Rubyforge上的重要项目之一。可以使用FreeRIDE来编写调试和执行Ruby代码,FreeRIDE内置了交互式变成环境和Ruby语言在线帮助,功能十分强大。Scintilla是一个免费的源代码编辑控件,它完全开放源代码,并允许用户自由地用于开源软件或是商业软件中。SciTE是用这个控件开发了一个编辑软件,在“One-Click Ruby Installer”中,SciTE集成了Ruby语言支持,使用起来非常方便。相比FreeRIDE,

26、它的特点就是使用简单。§2.2.3 使用fxriFxri是一个Ruby交互帮助和控制台工具。它不仅可作为语言的在线帮助,而且可以用作交互式Ruby解释器来执行程序。对于学习Ruby语言,fxri是一个非常方便的帮手。不知你有没有听说过FoxToolKit,它是相当轻巧的开放源代码的图形库。FXRuby是RubyForge上的一个项目,提供了Ruby语言使用Fox ToolKit的接口。而Fxri正是基于FXRuby开发,Fxri同样是RubyForge上的项目。这样你应该可以猜到Fxri名字的由来JFxri同时集成了Ruby-irb和Ruby-ri的功能,有了它,你可以抛开Ruby-

27、irb,Ruby-ri了,但如果你用的不是Windows系统的话,算我没说J§2.3Ruby-irbRuby-irb是交互式Ruby(Interactive Ruby)的简称,用来从标准输入读入并执行Ruby代码的工具,像一个shell。使用命令“irb”进入交互式模式,然后可以象输入命令行命令一样输入Ruby代码,代码执行的结果会立刻显示:§2.4Ruby-ri和Perl一样,Ruby也设计了嵌入式文档。 ruby-ri就是查看文档的工具。Ruby-ri的执行命令为“ri”,例如你可以通过“ri String.new”来查询String类的new方法:§2.5R

28、ubyGemsRubyGems是Ruby社区流行的包管理工具,在以前如果要下载一个Ruby扩展或者应用程序的话,你需要先下载相应的zip包,然后解压缩,再将应用或者扩展安装到Ruby对应的目录中。但是有了RubyGems所有这些麻烦都没有了,你只需要一条命令就可以从远程服务器上下载相应的包,如果相应的应用包含其他扩展,RubyGems会提示你从远程安装所依赖的扩展。安装后 RubyGems会运行相应的程序生成rdoc帮助文档。当然你也可以将软件包下载到本地运行RubyGems本地安装命令。统一化的管理带来的好处就是简单,有了RubyGems包管理器,Ruby应用的安装将变得前所未见的容易。Ru

29、byGems是Rubyforge下载量最大的项目之一,现在Ruby社区的应用都在朝着RubyGems的方向发展,RubyGems也将成为Ruby事实上的包管理器标准。RubyGems包管理器的可执行命令是“gem”,gem命令包含很多子命令和相应的选项,例如:gem -h/-help 显示命令帮助gem -v/-version 显示Gems的版本号第三章 类与对象Ruby是一种真正的面向对象程序设计语言,面向对象指以对象为中心的理论体系。l 封装(Encapsulation)将内部结构和算法隐藏起来,以确保只有特定的过程(也叫方法)才能直接操作数据,其结果是不能从外部直接使用数据构造,同时一旦

30、内部构造发生变化也不会对外界造成不良影响。这种隔离方法就叫做封装。l 继承l 多态(Polymorphism)根据对象的不同选择合适的操作。在Ruby中的实现方法是,根据被调的对象的不同来选择不同的方法。虽然有很多语言都宣称自己是面向对象的,但是他们往往对面向对象的解释都一样,大多是以自己特有的方式来解释什么是面向对象,而在实际情况中,这些面向对象语言又采用了很多非面向对象的做法。以 Java 为例:如果你想取一个数字取绝对值,java 的做法是:int num = Math.abs(-99);也就是将一个数值传递给 Math 类的一个静态函数 abs 处理。为什么这么做?因为在 java 中

31、,数值是基本类型不是类。而在 Ruby 中,任何事物都是对象,也就是说,数字99就是对象,取绝对值这样的操作应该属于数字本身,所以Ruby的做法就是:c = -99.abs在Ruby中,你所操作的一切都是对象,操作的结果也是对象。§3.1 类的定义类是对具有同样属性和同样行为的对象的抽象,Ruby中类的声明使用class关键字。定义类的语法如下,class ClassNamedef method_name(variables)#some codeendend类的定义要在classend之间,在上面的格式中,ClassName是类名,类名必须以大写字母开始,也就是说类名要是个常量。看下

32、面的例子:class Persondef initialize(name, gender, age)name = namegender = genderage = ageendend若某个类已经被定义过,此时又用相同的类名进行类定义的话,就意味着对原有的类的定义进行追加。class Testdef meth1puts "This is meth1"endendclass Testdef meth2puts "This is meth2"endend在Test类中,原有meth1方法,我们又追加了meth2方法,这时候,对于Test类的对象,meth1和m

33、eth2同样可用。§3.2 对象,属性和方法类在实例化后生成对象,在强调对象归属于某类时,有时候我们也使用实例对象一词。方法(Method)是对对象进行的操作。操作对象(被调)以self来表示。在Ruby中,除去内部类的对象以外,通常对象的构造都是动态确定的。某对象的性质由其内部定义的方法所决定。看下面的例子,我们使用new方法构造一个新的对象,class Persondef initialize(name, gender, age)name = namegender = genderage = ageendendpeople = Person.new('Tom',

34、'male', 15)我们可以使用Person.new方法来创建一个Person类的实例对象。以打头的变量是实例变量,他们从属于某一实例对象,Ruby中实例变量的命名规则是变量名以开始,您只能在方法内部使用它。initialize方法使对象变为“就绪”状态,initialize方法是一个特殊的方法,这个方法在构造实例对象时会被自动调用。对实例进行初始化操作时,需要重定义initialize方法。类方法new的默认的行为就是对新生成的实例执行initialize方法,传给new方法的参数会被原封不动地传给initialize方法。另外,若带块调用时,该块会被传给initializ

35、e方法。因此,不必对new方法进行重定义。在Ruby中,只有方法可以操作实例变量,因此可以说Ruby中的封装是强制性的。在对象外部不可以直接访问,只能通过接口方法访问。class Persondef namenameenddef gendergenderenddef ageageendendpeople = Person.new('Tom', 'male', 15)puts puts people.genderputs people.age输出结果为:Tommale15在Ruby中,一个对象的内部属性都是私有的。上面的代码中,我们定义了方法

36、name,gender,age三个方法用来访问Person类实例对象的实例变量。注意name,gender,age访问只能读取相应实例变量,而不能改变它们的值。我们也可以用成员变量只读控制符attr_reader来达到同样的效果。class Personattr_reader :name, :gender, :ageend类似地,我们可以定义方法去改变成员变量的值。class Persondef name=(name)name=nameenddef gender=(gender)gender=genderenddef age=(age)age=ageendendpeople = Person.

37、new('Tom', 'male', 15)= "Henry"people.gender= "male"people.age= 25也可以用成员变量写控制符attr_writer来达到同样的效果。class Personattr_writer :name, :gender, :ageend我们也可以使用attr_accessor来说明成员变量既可以读,也可以写。class Personattr_accessor :name, :gender, :ageend也可以使用attr控制符来控制变量是否可读写

38、。attr 只能带一个符号参数, 第二个参数是一个 bool 参数,用于指示是否为符号参数产生写方法。它的默认值是 false,只产生读方法,不产生写方法。class Personattr :name, true#读写attr :gender, true#读写attr :age, true#读写attr :id, false#只读end注意attr_reader,attr_writer,attr_accessor和attr不是语言的关键字,而是Module模块的方法。class Testattr_accessor :valueendputs Test.instance_methods - Te

39、st.superclass.public_methods执行结果为:valuevalue=上面代码中,我们使用Test.instance_methods得到Test类所有的实例方法,使用Test.superclass.public_methods得到Test父类所有的实例方法,然后相减就得到Test类不包含父类的所有的实例方法。由于instance_methods方法返回值为一个Array,所以我们作差值运算,Array的具体操作后面章节会讲到。也可以重定义方法,重定义一个方法时,新的定义会覆盖原有的定义。下面的例子重定义类中的方法meth1,class Testdef meth1puts &

40、quot;This is meth1"endenda = Test.newa.meth1class Testdef meth1puts "This is new meth1"endenda. meth1执行结果为:This is meth1This is new meth1重定义同一个类时,意味着对原有定义进行补充,不会覆盖原来的定义。而重定义方法时,则会覆盖原有定义。我们可以使用self标识本身,self和Java中的this有些类似,代表当前对象。class Persondef initialize(name, gender, age)name = nameg

41、ender = genderage = ageenddef <=>(other)self.age <=> other.ageendend<=> 方法通常意思为比较,返回值为-1,0或1分别表示小于,等于和大于。§3.3 继承Ruby继承的语法很简单,使用 < 即可。class Student < Persondef initialize(name, gender, age, school)name = namegender = genderage = ageschool = schoolendendRuby语言只支持单继承,每一个类都只

42、能有一个直接父类。这样避免了多继承的复杂度。但同时,Ruby提供了mixin的机制可以用来实现多继承。可以使用super关键字调用对象父类的方法,当super省略参数时,将使用当前方法的参数来进行调用。class Basedef meth(info)puts "This is Base #info"endendclass Derived < Basedef meth(info)puts "This is derived #info"superendendobj1 = Derived.newobj1.meth("test")执行结

43、果为:This is derived testThis is Base test如果传入的参数被修改再调用super的话,那么将会使用使用修改后的值。class Basedef meth(info)puts "This is Base #info"endendclass Derived < Basedef meth(info)puts "This is derived #info"info = "over"superendendobj1 = Derived.newobj1.meth("test")执行结果为:

44、This is derived testThis is Base over§3.4 特殊方法与特殊类特殊方法是指某实例所特有的方法。一个对象有哪些行为由对向所属的类决定,但是有时候,一些特殊的对象有何其他对象不一样的行为,在多数程序设计语言中,例如C+和Java,我们必须定义一个新类,但在Ruby中,我们可以定义只从属于某个特定对象的方法,这种方法我们成为特殊方法(Singleton Method)。class SingletonTestdef infoputs "This is This is SingletonTest method"endendobj1 =

45、SingletonTest.newobj2 = SingletonTest.newdef puts "This is obj2"执行结果为:This is This is SingletonTest methodThis is obj2有时候,我们需要给一个对象定义一系列的特殊方法,如果按照前面的方法,那么只能一个一个定义: def obj2.singleton_method1enddef obj2.singleton_method2enddef obj2.singleton_method3enddef obj2.

46、singleton_methodnend这样做非常繁复麻烦,而且无法给出一个统一的概念模型,因此Ruby提供了另外一种方法, class << objendobj是一个具体的对象实例,class << 代表它的特殊类。class SingletonTestdef meth1puts "This is meth1"enddef meth2puts "This is meth2"endendobj1 = SingletonTest.newobj2 = SingletonTest.newclass << obj2def me

47、th1puts "This is obj2's meth1"enddef meth2puts "This is obj2's meth2"endendobj1.meth1obj1.meth2obj2.meth1obj2.meth2执行结果为:This is meth1This is meth2This is obj2's meth1This is obj2's meth2§3.5 类变量与类方法类变量被一个类的所有实例对象共享,也可以被类方法访问到。类变量名以,开始,例如number。和全局变量,实例变量不同,类

48、变量在使用前必须初始化:class Personnumber = 0 #使用前必须有初值def initialize(name, gender, age)name = namegender = genderage = agenumber += 1endend类变量是私有的,在类外无法直接访问,你只能通过实例方法和类方法去访问它。同样,类方法是属于一个类的方法,定义类方法时需要在方法前加上类名:class Personnumber = 0 def initialize(name, gender, age)name = namegender = genderage = agenumber += 1

49、enddef Person.getNumber #类方法return numberendend除了Person.getNumber这种方式定义类方法外,还可以使用其它方式定义类方法,在后续章节可以陆续见到。§3.4 存取控制当你设计一个类时,你需要决定哪些属性和方法可以在类外被访问到,哪些属性和方法在类外被隐藏。如果一个类有过多的属性和方法在类外可以被访问到,那么势必破坏这个类的封装性。幸运的是在Ruby中,只能通过方法去改变一个类的属性,这样我们只需要考虑方法的存取控制。方法的存取控制有三种:l 公有方法(Public Method)n 方法在任何地方都可以被调用,这是方法的默认存

50、取控制。除了initialize和initialize_cpoy方法,他们永远是私有方法。l 保护方法(Protected Method)n 方法只能被定义这个方法的类自己的对象和这个类的子类的对象所访问。l 私有方法(private Method)n 方法只能被定义这个方法的类的对象自己访问,即使是这个类的其他对象也不能访问。Ruby中的保护方法和私有方法与一般面向对象程序设计语言的概念有所区别,保护方法的意思是方法只能方法只能被定义这个方法的类自己的对象和子类的对象访问,私有方法只能被对象自己访问。class Testdef method1 #默认为公有方法endprotected#保护方

51、法def method2endprivate#私有方法def method3endpublicdef test_protected(arg) #arg是Test类的对象arg.method2 #正确,可以访问同类其他对象的保护方法enddef test_private(arg)#arg是Test类的对象arg.method3 #错误,不能访问同类其他对象的私有方法endendobj1 = Test.newobj2 = Test.newobj1.test_protected(obj2)obj1.test_private(obj2)可以看到,和C+/Java相比,Ruby提供了更好的封装性。也可以

52、使用以下更简单的形式:class Testdef method1.enddef method2.enddef method3.enddef methdo4.endpublic:method1protected:method2private:method3, :method4endRuby和C+/Java的一个显著不同是存取控制是程序运行时决定的而不是静态绑定的。所以只有在访问一个受限制的方法时才会产生运行时错误。§3.6 元类在Ruby中一切都是对象。类和实例对象都是对象。这句话听起来有点拗口,让我们来看一个例子:class Persondef initialize(name, ge

53、nder, age)name = namegender = genderage = ageendenda = Person.new('Tom', 'male', 15)puts a.object_id=>22429840puts Person.object_id=>22429960没错,类也是对象,这是Ruby和C+/Java的一个显著不同,在C+/Java中,类仅仅是一个数据抽象,并没有类也是对象这样的概念。而在Ruby中存在着元类的概念,类也是对象,所有类都是元类的实例对象。和C+/Java相比,Ruby的面向对象程度更高。可以看到,类对象和实例

54、对象一样有自己的ojbect_id,你可以象调用一个实例对象的方法一样去用它去调用类方法。所有类对象的类是Class类,Oject类是所有类的基类。irb(main):003:0> Object.class=> Classirb(main):004:0> Object.superclass=> nil这样,我们可以从另一个角度去理解类变量与类方法,类变量就是一个类对象的实例变量,类方法就是指一个类对象类的特殊方法。类方法具体可分为两种:第一种是在所有的类的父类Class中定义的,且被所有的类所共享的方法;第二种是各个类所特有的特殊方法。类方法中的self指的是类本身,这

55、点需要牢记,这样我们可以使用多种方式定义类方法。class Test#定义类方法方式1def Test.meth1# .end#定义类方法方式2def self.meth2# .end#定义类方法方式3class << Testdef meth3# .endend#定义类方法方式4class << selfdef meth4# .endendend§3.7 Ruby的动态性可以重新定义同一个方法,class RedefTestdef methputs "This is meth"endendobj1 = RedefTest.newobj1.

56、methclass RedefTestdef methputs "This is new meth"endendobj1.meth执行结果为:This is methThis is new meth可以使用undef_method取消一个方法的定义,class UndefTestdef methputs "This is meth"endendobj1 = UndefTest.newobj1.methclass UndefTestundef_method(:meth)endobj1.meth执行结果为:This is methtest.rb:14: un

57、defined method meth' for #<UndefTest:0x2ac8240> (NoMethodError)§3.8 变量变量名长度只受内存大小的限制。可以通过区分Ruby变量名的首字符来区分它是局部变量、实例变量、类变量、全局变量还是常量。通常情况下,变量名的第二位字符以后是数字、字母或下划线,但有的内部变量名比较特殊,如“$?”。§3.8.1局部变量局部变量以小写字母或下划线开始。num = 1foo局部变量的作用域起始于声明处,结束于该声明所在的块、方法定义、类模块定义的结尾。2.times p defined?(num) num = 10 p num输出为:nil10nil10即使声明部分未被解释器执行仍有效,因为已经经过解释器的处理。v = 1 if falsep defined?(v)p v输出为:"local-variable"nil但若块已经变成过程对象的话,则局部变量将一直持续到该过程对象终结为止。若多个过程对象引用同一个作用域的话,局部变量将被这些对象所共享。(t

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论