




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Ruby语言
GrantRen
hyqryq@gmail.com
2006年11月24日
-W.-X-
刖s
目录
Ruby语言I
GrantReni
第一局部Ruby语言根基5
第一章Ruby语言概述5
§1.1Ruby的历史5
§1.2Ruby名字的由来6
§1.3Ruby的特点6
§1.4Ruby和Python的比照6
第二章Ruby编程环境7
§2.1Ruby的安装7
§2.1.1在Windows95/98/Me/XP上安装Ruby7
§2.1.2在Linux上安装Ruby7
§2.2运行Ruby7
§2.2.1使用Ruby7
§2.2.2使用FreeRIDE和SciTE8
§2.2.3使用fxri8
§2.3Ruby-irb8
§2.4Ruby-ri8
§2.5RubyGcms8
第三章类与对象9
§3.1类的定义9
§3.2对象,属性和方法10
§3.3继承12
§3.4特殊方法与特殊类13
§3.5类变量与类方法14
§3.4存取控制14
§3.6元类15
§3.7Ruby的动态性16
§3.8变量17
§3.8.1局部变量17
§3.8.2实例变量17
§3.8.3类变量18
§384全局变量18
§3.8.5常量18
§3.8与定义有关的操作19
§3.8.1alias19
§3.8.2undcf20
§3.8.3defincd?20
第四章根本类型22
§4.1Anay22
§4.2Hash23
§4.3Number23
§4.4String24
§4.5Rangc24
§4.6Symbol25
§4.7正则表达式26
第五章代码块和迭代器27
§5.1代码块(Block)27
§5.1.1什么是代码块27
§5.1.2代码块与对象27
§5.2迭代器(Iterator)28
§5.2.1什么是迭代器28
§5.2.2使用迭代器28
§5.2.3yield29
§5.2.4编写自己的迭代器29
第六章表达式30
§6.1运算符30
§6.2命令替换31
§6.3赋值运算符32
§6.4并行赋值32
§6.5嵌套赋值33
§6.6其他赋值33
§6.7条件运算34
§6.8case表达式35
§6.9循环36
§6.9.1Loop36
§6.9.2While36
§6.9.3Unlil36
§6.9.4Iterator36
§6.9.5For..In37
§6.9.6Break.Redo,Next37
$6.9.7Retry39
第七章方法39
§7.1运算符重定义41
§7.2变长参数41
§7.3块调用42
§7.4方法返回值42
第八章模块43
§8.1名字空间43
§8.2mixin44
§8.3使用mixin44
§8.3.1Comparable44
§8.3.2Enumcrable45
§8.3.3Singlc(on46
§8.4Require,load和includc46
第九章异常47
§9.1异常处理47
§9.2定义异常类50
§9.3catch和throw51
第十章多任务处理51
§10.1多线程处理52
§10.1.1线程创立52
§10.1.2线程操作53
§10.1.3线程和异常53
§10.1.4线程调度55
§10.1.5线程同步55
§10.2多进程处理59
§10.2.1进程创立60
第十一章根本I/O操作60
§11.1使用Kernel模块处理I/O操作61
§11.2文件处理61
§11.3StringIO61
§11.4Socket62
第十二章反射和对象空间62
§12.1ObjcctSpacc模块62
§12.2观察类和对象的状态64
§12.3动态方法调用65
§12.3.1使用send方法65
§12.3.2使用Method类和UnboundMethod类65
§12.3.3使用eval方法67
§12.3.4性能67
§12.4Hook和回调方法68
§12.4.1什么是Hook68
§12.4.2Ruby中的Hook68
§11.4.2回调方法69
§12.5跟踪程序的运行69
§12.5.1set_trace_func69
§12.5.2trace_var70
§12.5.3caller70
§12.5.3_FILE___LINE_和SCRIPT_LINES_70
第十三章序列化和YAML71
§13.1序列化的概念71
§13.2使用序列化71
§13.2.1二进制数据保存71
§13.2.2YAML数据保存71
§13.3定制序列化72
§13.3.1二进制数据保存72
§13.3.2YAML数据保存73
§13.3YAML73
§13.3.1集合类型74
§13.3.2单行集合类型76
§13.3.3根本类型76
§13.3.4块77
§13.3.5别名和锚(AliasesandAnchors)77
§13.3.6文档77
§13.3.7Ruby中YAML的使用77
第十四章安全控制77
§14.10级78
§14.11级78
§14.22级78
§14.33级78
§14.44级78
第十五章单元测试79
§15.1什么是单元测试79
§15.2Ruby单元测试框架79
第二局部内置类与模块79
第一章内置类79
§1.1Array79
§1.2Bignum79
§1.3Binding79
§1.4Class79
§1.5Continuation79
§1.6Dir8l
§1.7ExceptionsI
§1.8FalseClass81
§1.9File8l
§1.10File::Stat81
§1.11Fixnum81
§LI2Float81
§1.13Hash81
§1.14Integers1
§1.151081
§1.16MatchData81
§1.17Meth()d81
§1.18ModulesI
§1.19NilClass81
§1.20Numeric81
§1.21Object82
§1.22Proc82
§1.23Process::Status82
§1.24Range82
§1.25Rcgexp82
§1.26String82
§1.27Struct82
§1.28Struct::Tms82
§1.29Symbol82
§1.30Thrcad82
§1.31ThreadGroup82
§1.32Timc82
§1.33TrueCiass82
§1.34UnhoundMethod82
第二章内置模块82
§2.1Comparable83
§2.2Enumerable83
§2.3Error83
§2.4FileTest83
§2.5GC83
§2.6Kcrncl83
§2.7Marshal83
§2.8Ma(h83
§2.9Objcc(Spacc83
§2.10Process83
§2.11Process::GID83
§2.12Process::Sys83
§2.13Process::UID83
§2.14Signal83
第三局部Ruby语言总结84
附录87
§1术语对照87
第一局部Ruby语言根基
第一章Ruby语言概述
§l.lRuby的历史
Ruby语言的创造人是日本人松本行弘(MatsumotoYukihiro),大家亲切的称呼他"Malz"。
可能会出乎大家的意料,Ruby并不是一种近年来才诞生的语言,它的历史可以追溯到1993年,Ruby之父
Matz开场对脚本语言感兴趣.在通过•些分析和思考之后,Matz认为脚本语言是可以变得很强大和灵活的,
于是他准备把脚本语言作为他的开展方向。和很多人一样,Malz是一个面向对象程序设计的fans,自然而
然他想研究一种支持面向对象程序设i•的脚本语言。随后的一段时间,他到网络上搜集了一些相关的资料,
并且发现了Perl5,当时Perl5还没有发布。通过一段时间了解后,Matz.发现Perl5这并不是他想的东西,
所以他放弃了把Perl当作一个面向对象的脚本语言使用的念头。随后Matz转向了Python,Python是一个解
新型的、面向对象语言,但是Matz发现Pylhon并不能完全算作“面向对象”语言。Malz认为Python是面
向对象和过程化程序设计语言(ProceduralProgrammingLanguage)的混合产物。Malz希望找到扁是一种比
Perl更强大、比Python更面向对象的语言,但是很遗憾,这样的语言当时在地球上并不存在。于是Matz打
算自己设计一个全新的编程语言。1993年2月24日是一个值得纪念的日子,在这一天Ruby诞生了。1995
年12月Matz推出了Ruby的第一个版本Ruby0.95。在1996年以前,都是Matz.一个人在开发进展Ruby
的开发.后来随着Ruby社区的渐渐形成.很多科I乂成员给了Malz许多有意义的帮助,包括提交hug和patch
等。现在,Ruby像其他开源工程一样,有自己的开发团队,任何有能力的个人或团体都可以参与Ruby的开
发与进化。
§1.2Ruby名字的由来
首先明确一点,Ruby并不是其他单词的缩写。受Perl的影响,Maiz也想用一种宝石来命名他的新语言,
他使用了他的一位同事的生肖石一红宝石。后来,Matz意识到Ruby这个名字十分恰当,首先,在生肖石中,
Pearl代表六月,而Ruby代表七月。在字体大小上,Pearl大小是5pI,ruby的大小是5.5pi°所以Ruby这个名
字对于一种Perl的后续语言十分适宜。
§1.3Ruby的特点
Ruby是一种功能强大的面向对象的脚本语言,可以使用它方便快捷地进展面向对象程序设计。与Perl
类似,而且Ruby具有强大的文本处理功能,使文本处理变得简单。此外汇可以方便地使用C语言来扩展Ruby
的功能。
假设您曾经“想要一种简单的面向对象的语言",或者认为“Perl的功能虽然好用,但它的语法真让人
受不了",又或者觉得“LISP系列语言的思想不错,但到处都是括号真让人讨厌,最起码算式应该按照通常
的样式书写"。那么,Ruby或许能让您满意。
归纳起来,Ruby有以下优点:
•解释型执行,方便快捷
Ruby是解释型语言,其程序无需编译即可执行。
•语法简单、优雅
语法比照简单,类似Algol系语法。
•完全面向对象
Ruby从•开场就被设计成纯粹的面向对象语言,因此所有东西都是对象,例如整数等根本数据类型。
•内置正则式引擎,适合文本处理
Ruby支持功能强大的字符串操作和正则表达式检索功能,可以方便的对字符串进展处理。
・自动垃圾收集
具有垃圾回收(GarbageCollecl,GC)功能,能自动回收不再使用的对象。不需要用户对内存进展管理0
•跨平台和高度可移植性
Ruby支持多种平台,在Windows,Unix,Linux,MacOS上都可以运行。Ruby程序的可移植性非常好,
绝大多数程序可以不加修改的在各种平台上加以运行。
•有优雅、完善的异常处理机制
Ruby提供了一整套异常处理机制,可以方便优雅地处理代码处理出错的情况。
•拥有很多高级特性
Ruby拥有很多高级特性,例如操作符重载、Mix-ins、特殊方法等等,是用这些特性可以方便
地完成各种强大的功能。
同时,由于是解释型语言,Ruby也有以下缺点:
・解释型语言,所以速度较慢
・静态检查比照少
§1.4Ruby和Python的比照
Python是Ruby的劲敌。其功力深厚,可谓“千年蛇妖”。但matz认为Python的功能仍不完美,不然就
不会创造RubyTo
第二章Ruby编程环境
§2.1Ruby的安装
Ruby支持多种平台,包括Windows、Linux、各种类UNIX、MacOSX等。
§2.1.1在Windows95/98/Me/XP上安装Ruby
对于使用Windows平台的用户,安装Ruby是相当简单直接的事情。最方便的方法是使用“One-ClickRuby
Installer*„
不知你有没有听说过SourceForgeSourceForge是全球最大的开放源代码软件开发平台和仓库。它集成了
很多开放源代码应用程序,为软件开发提供了整套生命周期服务。在Ruby世界,也有一个类似的网站,那
就是Rubyforge。"Onc-ClickRubyInsiallcr"是Rubyforgc上的一个开源工程,也是Rubyforge上下载量最大
的工程之一。这个工程将Ruby语言核心和一系列常用扩展集成到了一起,还包含支持Ruby的免费的IDE
J^FreeRIDE和SciTE,除了这些之外还包括帮助文档,例如代码,RubyGcms包管理器,FoxGUI摩,fxri
InteractiveRubyHelp&Console)等。和正如它名字所示,使用它,Ruby安装变得前所未见的容易。你可以
在下面的地址下载到它的最新版本:
:〃ruby/Droiccls/rubyinstallni7
§2.1.2在Linux上安装Ruby
在linux下Ruby的安装要稍微复杂一些,推荐使用源码编译的方式安装,这样可以保证安装的是最新版
本。
首先到ru到主站:〃rubY-/en/下载源代码,下载完毕后解压到目录,然后使用以下命令:
./configure
./make;makeinstall
执行上面的命令需要root权限,默认安装到/usMocal下。你也可以使用“./configure-prefix:自定义路径”
来指定安装目录。
windows上的rubyonc-clickinstaller默认安装了RubyGcms,但在Linux下我们需要于•动安装RubyGcms。
RubyGems是一个Ruby的包管理器,我们后边会讲到它。
首先从Rubyforge卜载RubyGems的最近版本,地址如下:
://rubyforge.org/projccts/rubygems/
解乐RubyGems以后到相应目录下输入rubysetup.rb,屏幕卜.打印一些日志以后会告诉你安装成功,执
行gem-v可以查看一gem安装版本号。
§2.2运行Ruby
下面,我们将以Windows平台下的Ruby环境举例假设何运行Ruby。
§2.2.1使用Ruby
将“Hell。World"作为学习计算机语言第一个学写的程序,现在己经成为一种传统。该程序最早出现在
由BrianKcrnighan和DennisRitchie写的经典计算机程序设计教程《TheCProgrammingLanguage》。我们来
看看Ruby世界的“HelloWorld":
在Windows中,硼开命令行提示符窗口,在提示符上输入“Ruby”并回车,Ruby解新器就会运行井等
候输入程序。Ruby可执行文件应该包含在系统搜索路径内。
输入下面的程序:
print"HelloWorld!"
然后按Ctrl+D再按回车键,你就会看到Ruby执行程序的愉出结果:
你也可以先将代码保存为文件,然后便用再Ruby解释器执行:
§2.2.2使用FreeRIDE和SciTE
FreeRlDE是一个支持Ruby语言的免费IDE环境。FreeRIDE本身就是使用Ruby语言开发,它也是
Rubyforge上的重要工程之一。
可以使用FreeRIDE来编写调试和执行Ruby代码,FreeRIDE内置了交互式变成环境和Ruby语言在线都
助,功能十分强大。
Scintilla是一个免费的源代码编辑控件,它完全开放源代码,并允许用户自由地用于开源软件或是商业
软件中。SciTE是用这个控件开发了一个编辑软件,在“One-ClickRubyInstaller”中,SciTE集成了Ruby语
言支持,使用起来非常方便。相比FreeRIDE,它的特点就是使用简单。
§2.2.3使用fxri
Fxri是一个Ruby交互帮助和控制台I;具。它不仅可作为语言的在线帮助,而且可以用作交互式Ruby解释
器来执行程序。对于学习Ruby语言,fxri是一个非常方便的帮手。
不知你有没有听说过FoxToolKit,它是相当轻巧的开放源代码的图形库。FXRuby是RubyForge上的一个工
程,提供了Ruby语言使用FoxToolKit的接口。而Fxri正是基于FXRuby开发,Fxri同样是RubyForge上的工
程。这样你应该可以猜到Fxri名字的由来怎
Fxri同时集成了Ruby-irb和Ruby-ri的功能,有了它,你可以抛开Ruby-irb,Ruby-ri了,但如果你用的
不是Windows系统的话,和我没说⑥
§2.3Ruby-irb
Ruby-irb是交互式Ruby(InteractiveRuby)的简称,用来从标准输入读入并执行Ruby代码的工具,像
一个shello
使用命令"irb”进入交互式模式,然后可以象输入命令行命令一样输入Ruby代码,代码执行的结果会
立刻显示:
§2.4Ruby-ri
和Perl一样,Ruby也设计了嵌入式文档。ruby-ri就是查看文档的工具。Ruby-ri的执行命令为“ri”,
例如你可以通过“门JStnng.new"来查询String类的new方法:
§2.5RubyGems
RubyGcms是Ruby社区流行的包管理工具,在以前如果要下载一个Ruby扩展或者应用程序的话,你需
要先下载相应的zip包,然后解压缩,再将应用或者扩展安装到Ruby对应的目录中。但是有了RubyGems
所有这些麻烦都没有了,你只需要一条命令就可以从远程服务器上下载相应的包,如果相应的应用包含其他
扩展,RubyGems会提示你从远程安装所依赖的扩展。安装后RubyGerrs会运行相应的程序生成rdoc帮助文
档。当然你也可以将软件包下载到本地运行RubyGems木地安装命令。
统一化的管理带来的好处就是简单,有了RubyGems包管理器,Ruby应用的安装将变得前所未见的容易。
RubyGems是Rubyforge下载量最大的匚程之一,现在Ruby社区的应用都在朝着RubyGems的方向开展,
RubyGcms也将成为Ruby事实上的包管理器标准。
RubyGems包管理器的口J"执行命令是“gem",gem命令包含很多子命令和相应的选项,例如:
gem-h/-help-显示命令帮助
gem-v/—version-显示Gems的版本号
第三章类与对象
Ruby是一种真正的面向对象程序设计语言,面向对象指以对象为中心的理论体系。
•封装(Encapsulation)
将内部构造和算法隐藏起来,以确保只有特定的过程(也叫方法)才能直接操作数据,其结果是不能从外
部直接使用数据构造,同时一旦内部构造发生变化也不会对外界造成不良影响。这种隔离方法就叫做封装。
•继承
•多态(Polymorphism)
根据对象的不同选择适宜的操作。在Ruby中的实现方法是,根据被调的对象的不同来选择不同的方法。
虽然有很多语言都宣称自己是面向对象的,但是他们往往对面向对象的解释都一样,大多是以自己特有
的方式来解释什么是面向对象,而在实际情况中,这些面向对象语言又采用了很多非面向对象的做法。
以Java为例:如果你想取•个数字取绝对位,java的做法是:
in(num=Ma(h.abs(-99);
也就是将一个数值传递给Math类的一个静态函数abs处理。为什么这么做因为在java中,数值是
根本类型不是类。
而在Ruby中,任何事物都是对象,也就是说,数字-99就是对象,取绝对值这样的操作应该属于数字
本身,所以Ruby的做法就是:
c=-99.abs
在Ruby中,你所操作的一切都是对象,操作的结果也是对象。
§3.1类的定义
类是对具有同样属性和同样行为的对象的抽象,Kuby中类的声明使用class关键字。定义类的语法如下,
classClassName
defmethod_name(variables)
#somecode
end
end
类的定义要在Sass…end之间,在上面的格式中,ClassName是类名,类名必须以大写字母开场,也
就是说类名要是个常量。
看下面的例子:
classPerson
definitialize(name,gender,age)
©name=name
Qgender=gender
Gage=age
end
end
假设某个类已经被定义过,此时又用一样的类名进展类定义的话,就意味着对原有的类的定义进展追加。
classTest
defmethl
puts"Thisismethl"
end
end
classTest
defmeth2
puts"Thisismeth2"
end
end
在Test类中,原有methl方法,我们又追加了meth2方法,这时候,对于Test类的对象,methl
和meth2同样可用。
§3.2对象,属性和方法
类在实例化后生.成对象,在强调对象归属丁某类时,有时候我们也使用实例对象一词。
方法[Method)是对对象进展的操作。操作对象(被调)以self来表示。在Ruby中,除去内部类的对象以
外,通常对象的构造都是动态确定的。某对象的性质由其内部定义的方法所决定。
看下面的例子,我们使用new方法构造一个新的对象,
classPerson
definitialize(name,gender,age)
Qname=name
©gender=gender
©age=age
end
end
people=Person.new(*Tom','male',ib)
我们可以使用Person.ne翼方法来创立一个Person类的实例对象。以©打头的变量是实例变量,他们
附属于■某一实例对象,Ruby中实例变量的命名规则是变量名以@开场,您只能在方法内部使用它。
initialize方法使对象变为"就绪"状态,initialize方法是一个特殊的方法,这个方法在构造
实例对象时会被自动调用。
对实例进展初始化操作时,需要重定义initialize方法。类方法new的默认的行为就是对新生成的
实例执行initialize方法,传给new方法的参数会被原封不动地传给initialize方法。另外,假设带
块调用时,该块会被传给initialize方法。因此,不必对new方法进展重定义。
在Ruby中,只有方法可以操作实例变量,因此可以说Ruby中的封装是弗制性的。在对象外部不可以直
接访问,只能通过接口方法访问。
classPerson
defname
©name
end
defgender
©gender
end
defage
Gage
end
end
people=Person.new(1Tom','male*,15)
puts
putspeople.gender
putspeople.age
输出结果为:
Tom
male
15___________________
在Ruby中,一个对象的内部属性都是私有的,上面的代码中,我们定义[史法name,gender,age三个
方法用来迈问Person类实例对象的实例变量。注意name,gender,age访问只能读取相应实例变量,而不能
改变它们的值。
我们也可以用成员变量只读控制符attrreader来到达同样的效果。
classPerson
attx_reader:name,:gender,:age
end
类似地,我们可以定义方法去改变成员变量的值。
classPerson
defname=(name)
@name=name
end
defgender=(gender)
@gender=gender
end
defage=(age)
@age=age
end
end
people=Person.new(*Tom','male*,15)
people.name="'Henry"
people.gender="male"
people.age=25
也可以用成员变量写控制符attr_writer来到达同样的效果。
classPerson
attr_writer:name,:gender,:age
end
我们也可以使用attjaccessor来说明成员变量既可以读,也可以写。
classPerson
attr_accessor:name,:gender,:age
end
也可以使用attr控制符来控制变量是否可读写。attr只能带一个符号参数,第二个参数是一个bool
参数,用于指示是否为符号参数产生写方法。它的默认值是false,只产生读方法,不产生写方法。
classPerson
attr:name,true#读写
attr:gender,true#读写
attr:age,true#读写
attr:id,false#只读
end
注意attr_reader,attr_writer,attr_accessor和attr不是语言的关键字,而是Module
模块的方法。
classTest
attr_accessor:value
end
putsTest.instance_methods-Test.superclass.public_methods
执行结果为:
value
value=
上面代码中,我们使用Test.instance_methods得到rest类所有的实例方法,使用
Test.superclass.public_methods得至UTest父类所有的实例方法,然后相减就得到Test类不包含
父类的所有的实例方法。
由于instance_methods方法返回值为一个Array.所以我们作差值运算,Array的具体操作后而
章节会讲到。
也可以重定义方法,重定义一个方法时,新的定义会覆盖原有的定义。
下面的例子重定义类中的方法me二hl,
classTest
defmethl
puts"Thisismethl1'
end
end
a=Test.nevz
a.methl
classTest
defmethl
puts''Thisisnewmethl"
end
end
a.methl
执行结果为:
Thisismethl
Thisisnewmethl
重定义同一个类时,意味着对原有定义进展补充,不会覆盖原来的定义。而重定义方法时,则会覆盖原
有定义C
我们可以使用self标识本身,self和Java中的Ihis有些类似,代表当前对象。
classPerson
definitialize(name,gender,age)
©name=name
©gender=gender
@age=age
end
def<=>(other)
self.age<=>other.age
end
end
<=>方法通常意思为比照,返回值为0或1分别表示小于,等于和大于。
§3.3继承
Ruby继承的语法很简单,使用<即可。
classStudent<Person
definitialize(name,gender,age,school)
@name=name
Qgender=gender
@age=age
^school=school
end
©nd
Ruby语言只支持单继承,每一个类都只能有一个直接父类。这样防止了多继承的复杂度。但同时,Ruby
提供了mixin的机制可以用来实现多继承。
可以使用super关键字调用对象父类的方法,当super省略参数时,将使用当前方法的参数来进展调
用。
classBase
defmeth(info)
puts"ThisisBase#{info}"
end
end
classDerived<Base
defmeth(info)
puts"Thisisderived#{info}',
super
end
end
obj1=Derived.new
obj1.meth("test")
执行结果为:
Thisisderivedtest
ThisisBasetest
如果传入的参数被修改再调用super的话,那么将会使用使用修改后的值。
classBase
defmeth(info)
puts"ThisisBase#{info}*'
end
end
classDerived<Base
defmeth(info)
puts*'Thisisderived#{info)"
info="over"
super
end
end
obj1=Derived.new
obj1.meth("test")
执行结果为:
Thisisderivedtest
ThisisBaseover
§3.4特殊方法与特殊类
特殊方法是指某实例所特有的方法。一个对象有哪些行为由对向所属的类决定,但是有时候,一些特殊
的对象有何其他对象不一样的行为,在多数程序设计语言中,例如C++和Java,我们必须定义一个新类,但
在Ruby中,我们可以定义只附属于某个特定对象的方法,这种方法我们成为特殊方法(SingletonMethod)。
classSinqletonTest
definfo
puts"ThisisThisisSingletonTestmethod"
end
end
obj1=SingletonTest.new
obj2=SingletonTest.new
defobj2.info
puts"Thisisobj2n
end
obj1.info
obj2.info
执行结果为:
ThisisThisisSingletonTestmethod
Thisisobj2
芍时候,我们需要给一个对象定义一系列的特殊方法,如果按照前面的方法,那么只能一个一个定义:
defobj2.singleton_methodl
end
defobj2.singleton_method2
end
defobj2.singleton_method3
end
defobj2.singleton_methodn
end
这样做非常繁复麻烦,而且无法给出一个统一的概念模型,因此Ruby提供了另外一种方法,
class<<obj
end
obj是一个具体的对象实例,class«代表它的特殊类。
classSingletonTest
defmethl
puts"Thisismethl"
end
defmeth2
puts''Thisismeth2"
end
end
obj1=SingletonTest.new
obj2=SingletonTest.new
class<<obj2
defmethl
puts"Thisisobj2*smethl"
end
defmeth2
puts"Thisisobj2*smeth2u
end
end
obj1.methl
obj1.meth2
obj2.methl
obj2.meth2
执行结果为:
Thisismethl
Thisismeth2
Thisisobj21smethl
Thisisobj2*smeth2
§3.5类变量与类方法
类变量被一个类的所有实例对象共享,也可以被类方法访问到,类变量名以开场,例如
和全局变量,实例变量不同,类变量在使用前必须初始化:
classPerson
@@number=0#使用前必须有初值
definitialize(name,gender,age)
Gname=name
@gender=gender
Gage=age
@©number+=1
end
end
类变量是私有的,在类外无法直接访问,你只能通过实例方法和类方法去访问它。
同样,类方法是属于一个类的方法,定义类方法时需要在方法前加上类名:
classPerson
©©number=0
definitialize(name,gender,age)
0name=name
©gender=gender
@age=age
◎©number+=1
end
defPerson.getNumber#类方法
return@©number
end
end
除了Person.getNumber这种方式定义类方法外,还可以使用其它方式定义类方法,在后续章节可以
陆续见到。
§3.4存取控制
当你设计•个类时,你需要决定哪些属性和方法可以在类外被访问到,哪些属性和方法在类外被隐藏。
如果一个类有过多的属性和方法在类外可以被访问到,那么势必破坏这个类的封装性。幸运的是在Ruby中,
只能通过方法去改变一个类的属性,这样我们只需要考虑方法的存取控制。
方法的存取控制有三种:
・公有方法(PublicMethod)
■方法在任何地方都可以被调用,这是方法的默认存取控制。除了initialize和
initialize_cpoy方法,他们永远是私有方法。
•保护方法(ProtectedMethod)
■方法只能被定义这个方法的类自己的对象和这个类的子类的对象所访问。
•私有方法(privateMethod)
■方法只能被定义这个方法的类的对象自己访问,即使是这个类的其他对象也不能访问。
Ruby中的保护方法和私有方法与一般面向对象程序设计语言的概念有所区别,保护方法的意思是方法
只能方法只能被定义这个方法的类自己的对象和子类的对象访问,私有方法只能被对象自己访问。
classTest
defmethodi#默认为公有方法
end
protected#保护方法
defmethod2
end
private#私有方法
defmethods
pnd
public
deftest_protected(arg)#arg是Test类的对象
arg.method24正确,可以访问同类其他对象的保护方法
end
deftest_private(arg)#arg是Test类的对象
arg.n^thod3#错误,不能访问同类其他对象的私有方法
end
end
obj1=Test.new
obj2=Test.new
obj1.test_protected(obj2]
obj1.test._privat.e(obj2)
可以看到,和C+1/Java相比,Ruby提供了更好的封装性。
也可以使用以下更简单的形式:
classTest
defmethodi
end
defmethod2
end
defmethod3
end
defmethdo4
end
publicimethodl
protected:method2
private:method3z:method4
end
Ruby和C++/Java的一个显著不同是存取控制是程序运行时决定的而不是静态绑定的。所以只有在访问
一个受限制的方法时才会产生运行时错误。
§3.6元类
在Ruby中一切都是对象。类和实例对象都是对象。这句话听起来有点拗口,让我们来看一个例子:
classPerson
definitialize(name,gender,age)
Qname=name
Ggender=gender
Cage=age
end
end
a=Person.new(*Tom1,'male',15)
putsa.object_id=>22429840
putsPerson.object_id=>22429960
没错,类也是时象,这廷'Ruby和C++/Java的一个显著不同,在C++/Java中,类仅仅是一个数据
抽象,并没有类也是对象这样的概念。而在Ruby中存在着元类的概念,类也是对象,所有类都是元类的实
例对象。和C++/Java相比,Ruby的面向对象程度更高。
可以看到,类对象和实例对象一样有自己的ojbect_id,你可以象调用一个实例对象的方法一样去用
它去调用类方法。所有类对象的类是Class类,Oject类是所有类的基类。
irb(main):003:0>Object.class
=>Class
irb(main):004:0>Object.superclass
=>nil
这样,我们可以从另•个角度去理解类变量与类方法.类变量就是•个类对象的实例变量,类方法玳是
指一个类对象类的特殊方法。
类方法具体可分为两种:第一种是在所有的类的父类Class中定义的,且被所有的类所共享的方法:第
二种是各个类所特有的特殊方法。
类方法中的self指的是类本身,这点需要牢记,这样我们可以使用多种方式定义类方法。
classTest
北定义类方法方式1
defTest.methl
#...
end
步定义类方法方式2
defself.meth2
♦…
end
年定义类方法方式3
class«Test
defmeth3
#...
end
end
#定义类方法方式4
class<<self
defmeth4
#...
end
end
end
§3.7Ruby的动态性
可以重新定义同一个方法,
classRedefTest
defmeth
puts"Thisismeth”
end
end
OJDJ1=RedetTest.new
obj1.meth
classRedefTest
defmeth
puts"Thisisnewmeth”
end
end
obj1.meth
执行结果为:
Thisismeth
Thisisnewmeth
可以使用undef_method取消•个方法的定义,
classUndefTest
defmeth
puts"Thisismeth”
end
end
obj1=UndefTest.new
obj1.meth
classUndefTest
undef_method(:meth)
end
obj1.meth
执行结果为:
Thisismeth
test.rb:14:undefinedmethod'meth*for#<UndefTest:0x2ac8240>(NoMethodError)
§3.8变量
变量名长度只受内存大小的限制。可以通过区分Ruby变量名的首字符来区分它是局部变量、实例变量、
类变量、全局变量还是常量。通常情况下,变量名的第二位字符以后是数字、字母或下划线,但有的内部变
量名比照特殊,如。
§3.8.1局部变量
局部变量以小写字母或下划线开场。
num=1
foo
局部变量的作用域起始于声明处,完毕于该声明所在的块、方法定义、类/模块定义的结尾。
2.times{
pdefined?(num)
num=10
pnum
}
输出为:
nil
10
nil
10
即使声明局部未被解释器执行仍有效,因为已经经过解释器的处理。
v=1iffalse
pdefined?(v)
Pv
输出为:
"local-variable**
nil
但假设块已经变成过程对象的话,则局部变量将一直持续到该过程对象终结为止。假设多个过程对
象引用同一个作用域的话,局部变量将被这些对象所共享。
(to-do例子)
§3.8.2实例变量
以@开场的变量是实例变量,实例变量属于特定的对象。
classPerson
definitialize(name,gender,age)
©name=name
Qgender=gender
Gage=age
end
end
上面的例子中,@name,@gender,@age都是实例变量。可以在类或子类的方法中引用实例变量.假
设引用尚未被初始化的实例变量的话,其值为nil.
§3.8.3类变量
以@@开场的变量是类变量c类变量在类的定义中定义.可以在类
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 护理规培出科汇报
- 2025年工业缝纫机电控项目合作计划书
- 2025年无功功率自动补偿装置项目合作计划书
- 玉树市重点中学2025届高三第三次模拟考试化学试卷含解析
- 2025年数控组合机床项目发展计划
- 五年级数学(小数四则混合运算)计算题专项练习及答案
- 2025年螺旋锥齿轮项目可行性建设方案
- 2025年非调质钢合作协议书
- 2025年泡丝剂项目合作计划书
- 2025年FS-L系列柔软剂项目发展计划
- 新概念二册课文电子版
- 动物传染病的传染与流行过程(动物传染病)
- 北师大五下《包装的学问》评课稿
- CNAS-GL039 分子诊断检验程序性能验证指南
- 【高中生物】染色体变异课件 高一下学期生物人教版必修2
- 2018年中考化学双向细目表
- 院内按病种分值付费(DIP)专题培训
- DBJ51-143-2020 四川省公共建筑节能设计标准
- 全国英语等级考试一级真题及答案
- 农村一二三产业融合项目可行性研究报告
- GB/T 9581-2011炭黑原料油乙烯焦油
评论
0/150
提交评论