Ruby语言入门教程v0.4

GTKWave 贡献于2010-09-01

作者 张开川  创建于2007-01-18 10:15:00   修改者张开川  修改于2007-01-18 10:15:00字数14860

文档摘要:松本行弘(Matz)是日本一家开源软件公司的程序员,有15年的编程经验。在工作中,他希望有一种比Perl强大,比Python更面向对象的语言。从1993年2月,他开始设计一个全新的自己的语言,1994年12月发布了第一个alpha版本,并且将这种新语言定名为Ruby(红宝石)。
关键词:

 Ruby语言中文教程 Ruby语言入门教程 Version 0.4 编著 张开川 kaichuan_zhang@126.com 第 页 Ruby语言入门教程v0.4 目录 自序 3 第一章 概述 4 1.1 编程语言的发展简史 4 1.2 编程其实很容易 5 1.3 Ruby的由来 6 1.4 Ruby的特性 7 第二章 8 2.1 下载Ruby 1.8.5 8 2.2 安装Ruby 1.8.5 for Windows 8 2.3 开始第一个小程序 10 2.4 ruby语言的集成开发环境 12 第三章 语法快览 14 3.1 注释与分行 14 3.2 分隔符 15 3.3 关键字 16 3.4 运算符 17 3.5 标识名和变量的作用域 19 3.6 类库 19 3.7 数据类型 20 3.8 赋值和关系运算符 21 3.9 条件判断语句 22 3.10 循环语句 24 3.11 常与线程 26 3.12 一个综合小练习 27 第四章 一切都是对象 28 4.1 两种思维方式 28 4.2 对象 29 4.3 封装 30 4.4 继承 32 4.5 多态 33 小跋 34 第 页 Ruby语言入门教程v0.4 自序 其它编程语言的学习都主要来自于书本,而Ruby的学习却是完全经由网络。我想,回报网络的最好方式就是在网络上还没有Ruby中文书籍的时候,编著一本Ruby中文入门教材。感谢编程语言发展史上的前辈们;感谢网络论坛上程序员们或是理智,或是激烈的讨论;感谢一切看到这本书的人。 曾经经受了SCJP的挖掘、挖掘、再挖掘(基于1.4,还没有Java 5,Java 6的许多特性),初遇Ruby,觉得十分亲切,仿佛童年时得到一个新奇的玩具。把玩之后,才发现玩具的塑料外壳里,藏着一把瑞士军刀。自此,模式、框架常常变得多余,很多时候可以更直接。好比在量子时代,星际航行只是一次时空转换而已,航天飞机静静地躺在博物馆里,那是旧时代科学的极致代表。 从物理课本中,我们感受到爱因斯坦的伟大,但对牛顿则怀以更加崇敬的心情。身体终将消逝,而你,我,他——我们的意识却将在网络中延续。旧时代文明的延续依赖于纸质书籍,书籍传递了理性之光。也许直觉才是这个宇宙本体的最初相用,直觉是一种天赋,我无从把握,但是理性,如此真切实在,她照亮了我,照亮了你,直到未来。 思,亘古如斯又倏忽闪现,谁的惊愕能深究它。 ——海德格尔 张开川 2006年12月31 第 页 Ruby语言入门教程v0.4 第一章 概述 1.1 编程语言的发展简史 本小节是一些编程语言的简单介绍,你如果不感兴趣,可以略过不看。 先说程序是什么?程序就是指令序列的有序集合。指令即代码,可以是数字,也可以是文字,文字最终要转换成数字。也就是说,程序是许多数字串,当然,也可以合并成一个很长很长的数字串。 程序的作用是什么?程序能够做事,做你想叫它做的事。用学术语言来说,程序的功能是完成它的使命。它的使命由编写程序的人来决定,或者由编写程序的程序来决定。 编写程序就是写文章,写能够转换成很长很长数字串的文章,给计算机看。 最初的计算机编程语言是一长串二进制代码。所谓的二进制就是只有1和0,所以第一代的计算机编程语言就象下面的许多1和0。 1001101001010011 0100011101111110 1010101000010100 11110100001010001 …… 这是给计算机看的,你看不懂,我也看不懂,程序员自己下次再看的时候,也是搞不清。但是,这是最基本的。直到现在,计算机的中央处理器(CPU)还是只认1和0组成的二进制代码。 第二代的计算机编程语言叫汇编语言,就象这样: LD x,37H 第 页 Ruby语言入门教程v0.4 MOV a,x …… 程序员之间能够很容易地交流,但是这样的语言编写效率很低,而且不同的CPU有不同的指令集,根本无法重复使用。 第三代的计算机编程语言称之为高级语言。容易编写,容易阅读,容易交流,而且可以与CPU、操作系统无关。从1958年的LISP和1957年的FORTRAN开始到现在,我们接触到的编程语言几乎都是第三代语言。其中又有两大类。一类叫函数式语言,如:LISP,Haskell。一类叫命令式语言,如:FORTRAN,Pascal,C++,Java。 第四代的计算机编程语言,你只要告诉它你要什么,无须告诉它怎么做,它就能把答案给你。上个世纪八十年代末发展起来的数据库查询语言(SQL)就是一个例子。第四代的编程语言还在起步阶段,智能化程度还有待于加强。SQL是当今最为强大的数据检索机制之一;SQL并不能完成一个过程语言所能完成的所有任务。 需要说明的是,面向对象的编程语言并不是第四代语言。面向对象是一种认识事物的方式、理念,你可以面向对象地编程(OOP),也可以面向对象地设计(OOD)。面向对象的编程语言是过程语言的自然延续,同属于第三代命令式语言。 大家平常所说的编程语言是指第三代的计算机编程语言。有的语言是解释执行,如Python,Ruby,交互性很好;有的语言是编译执行,如Pascal, C,速度较快。 有的语言是本地执行,如C,C++;有的语言是虚拟机执行,如Java, C#。有的语言是动态语言,如JavaScript,Ruby;有的语言是静态语言,如C++,Java。 1.2 编程其实很容易 一门语言包含三个方面:语义,语法和语用。汉语,英语是如此,计算机编程语言也是如此。 从语义方面来看,人类语言的单词量非常大,要以万计,常用单词也有几千;计算机编程语言的基本单词只有几十个,我们称之为关键字。 第 页 Ruby语言入门教程v0.4 学习一门计算机编程语言只要搞清楚这几十个关键字的意思、用法,就大致及格了,六十分到手了。如果要灵活应用一门计算机编程语言,就必须在反复使用的过程中去不断加强理解,不断加深体会。如果碰上好的教材,遇到好的老师,那么入门拿到六十分是很容易的。要想拿到八十分、九十分,就看各人修行了,所谓拳不离手,曲不离口。多多练习,“无它,但手熟尔”。 Ruby是一种动态语言,语法简单,就象当年的BASIC一样,非常容易上手,适合初学者。对于编程高手来说,Ruby里有许多深奥之处,等待你去发掘。 1.3 Ruby的由来 松本行弘(Matz)是日本一家开源软件公司的程序员,有15年的编程经验。在工作中,他希望有一种比Perl强大,比Python更面向对象的语言。从1993年2月,他开始设计一个全新的自己的语言,1994年12月发布了第一个alpha版本,并且将这种新语言定名为Ruby(红宝石)。发展到现在,最新版本是Ruby 1.8.5(2006-8-25)。 第 页 Ruby语言入门教程v0.4 1.4 Ruby的特性 计算机编程语言的发展总是与飞速变化的世界息息相关的,Ruby是为了适应变化、提高和完善编程艺术而出现的。 ● 完全开源 ● 多平台 Ruby可以运行在Linux,UNIX,Windows, MS-DOS, BeOS,OS/2… ● 多线程 线程(Thread)就是指能在一个程序中处理若干控制流的功能。与OS提供的进程不同的是,线程可以共享内存空间。 Ruby中使用的线程是用户级线程,由Ruby解释器进行切换管理。其效率要低于由OS管理线程的效率,且不能使用多个CPU,这确实是它的缺点。但其优点也很明显,即可移植性很高。 ● 完全面向对象 ● 不需要内存管理 具有垃圾回收(Garbage Collect,GC)功能,能自动回收不再使用的对象。 ● 解释执行 其程序无需编译即可轻松执行。相应地,速度较慢 ● 功能强大的字符串操作/正则表达式 ● 具有异常处理功能 ● 可以直接访问OS Ruby可以使用(UNIX的)绝大部分的系统调用。单独使用Ruby也可以进行系统编程。 ● 动态类型语言 Ruby的变量没有类型,因此不必为类型匹配而烦恼。相应地,静态检查功能也变弱了。 ● 动态语言 程序运行中,可以新加入属性,行为,也可以重写方法。 ● 支持操作符重载 ● 支持无限精度的数字 例如计算400的阶乘也轻而易举。 ● 丰富的库函数 ● 用模块进行混合插入(Mixin) Ruby舍弃了多重继承,但拥有混合插入功能。使用模块来超越类的界限来共享数据和方法等。 ● 语法简单 它是脚本语言,没有指针,学习曲线比较低。. …… Ruby吸取了perl的正则表达式,python的简单性可读性,smalltalk的纯面向对象语法和单继承, 第 页 Ruby语言入门教程v0.4 lisp的无穷嵌套的语法,java的线程… 第二章 你如果只是想了解Ruby语言,不准备实践,请跳过本章,从第三章开始我们的Ruby语言之旅。 2.1 下载Ruby 1.8.5 首先下载Ruby 1.8.5(2006-8-25) for Windows: 在网页http://www.rubychina.net/downloads/ 上找到 --〉Ruby on Windows --〉Ruby 1.8.5 One-Click Installer Stable version (recommended) 点击鼠标右键,另存为…,存入你的本地硬盘,这就完成了下载。 2.2 安装Ruby 1.8.5 for Windows 运行下载好的文件ruby185-21,出现安装向导界面, 点击next; 点击 I Agree; 点击next; 出现如下的 选择安装位置 界面, 第 页 Ruby语言入门教程v0.4 改变你想安装Ruby的路径,我选择了e:盘; 点击next; 点击Install; 点击next; 点击Finish,一切OK,安装完成。 第 页 Ruby语言入门教程v0.4 2.3 开始第一个小程序 从Windows XP的开始—〉运行 —〉输入cmd,打开一个DOS窗口; 1. 版本 输入 ruby –v , 屏幕显示了版本号。 2.开始第一个小程序,打印“hello,world” 第一种方式: 输入 ruby –e ‘print “hello,world” ’ , ruby 的意思:运行这个ruby语言程序; -e 的意思:把后面的一行脚本作为一个ruby程序; print 的意思:打印; hello,world 的意思:这是我们要输出的内容。 第 页 Ruby语言入门教程v0.4 第二种方式: ruby语言自带了一个交互式的编程环境irb,这是一个shell窗口。在e:\ruby , 输入: irb ; 输入: print "hello world" ; 输入: print "中文world" ; 如果要退出irb交互式环境,输入: exit 。 第三种方式: 你如果觉得上面的方式太繁琐,请在e:\ruby下 ,输入下面图示内容: 第 页 Ruby语言入门教程v0.4 2.4 ruby语言的集成开发环境 上一节第三种方式编写代码与运行程序分开操作,你很不习惯。这一节,我们试着建立ruby语言的集成开发环境。 1. 使用 Eclipse 开发ruby应用程序 Eclipse是一个功能强大的跨平台集成开发环境,支持对java,jsp,php等的开发,若是开发ruby应用程序,需要下载并配置RDT(Ruby Development Tools),一组Eclipse插件。 运行Eclipse 需要jre。编程语言的初学者,不熟悉Java,所以我不详细介绍Eclipse + RDT 的搭建。如果你是一个Java程序员,下载并配置RDT是很easy的。 2. 使用 ruby 自带的集成开发环境 Ruby 1.8.5 for Windows 自带了一个集成开发环境FreeRIDE,和一个代码编辑工具SciTE 。后面的程序我们将使用SciTE 编辑并运行ruby程序。 点击Windows XP的开始 —〉所有程序 —〉Ruby-185-21 —〉SciTE , 打开的窗口是英文,关闭它。去SciTE 的网站下载一个文件 locale.zh_gb.properties (10k),改名为 locale.properties 复制到 E:\ruby\scite\ 下,重新打开 SciTE , 第 页 Ruby语言入门教程v0.4 OK,都是中文了。今后,你在SciTE 中写好代码,保存为 .rb 文件(文件扩展名必须是rb )。选择菜单栏上的工具 —〉 运行,或者按下键盘 F5 键,就看到了执行结果。 第 页 Ruby语言入门教程v0.4 第三章 语法快览 第二章的内容可以跳过不看,本章的内容虽然不需要熟记,但是应该建立一个大致印象,为后面章节的内容打下基础。 3.1 注释与分行 Ruby中的注释有单行与多行两种,先看一个程序E3.1-1.rb: # E3.1-1.rb 从#开始到行尾是单行注释 puts 3/5 puts 3/5.0 =begin puts 6/5 puts 6/5.0 多行注释可以用=begin 和 =end ; 实际上,这也是Ruby的内嵌文档(Rdoc)注释,类似javadoc , 可以用命令 r i 从源文件生产文档。 =end 运行结果: >ruby E3.1-1.rb 0 0.6 第 页 Ruby语言入门教程v0.4 >Exit code: 0 Rdoc是内嵌在ruby代码之中的,可以转换为html文档说明。类似javadoc。 ri 是一个命令行程序,用来查看函数说明、类说明。函数说明、类说明应该放置在 =begin 和 =end 之中。 Ruby中用分号“ ; ”来表示一个语句的结束。一行如果有多个语句,每个语句用分号隔开,而最后一个语句可以省略分号。换行符表示一行结束。如果语句太长,可以用“ \ ”连接下一行。看程序E3.1-2.rb: # E3.1-2.rb 演示分行 puts 3/5 ; puts 3/5.0 puts "这里演示" \ "连行" 运行结果: >ruby E3.1-2.rb 0 0.6 这里演示连行 >Exit code: 0 3.2 分隔符 关键字、运算符、分隔符一起构成了一门编程语言的基本定义。3.2 、3.3 、3.4节分别对分隔符、关键字、运算符作一些介绍。如果有不详细的地方,将在本书后面部分介绍;或者是因为这些不重要,很少用到;还有一种情况是:可以被其它常用语法定义代替。 第 页 Ruby语言入门教程v0.4 Ruby中的常用分隔符如下: 符号 名称 用途 ; 分号 用来分隔一行中的多个语句 () 圆括号 提高优先级;定义方法时容纳参数列表 空格 分隔字符;在可省略()的地方,代替() , 逗号 隔开多个参数 . 点 将对象与它的方法隔开 :: 紧连的两个冒号 域作用符,将模块(类)与它的常量隔开 3.3 关键字 Ruby中的关键字如下: 模块定义:module 类定义: class 方法定义:def , undef 检查类型:defined? 条件语句:if , then , else , elsif ,case ,when ,unless 循环语句:for ,in ,while ,until ,next, break ,do , redo ,retry ,yield 逻辑判断:not ,and ,or 第 页 Ruby语言入门教程v0.4 逻辑值和空值:true ,false , nil 异常处理:rescue ,ensure 对象指针:super ,self 块的起始:begin/end 嵌入模块:BEGIN ,END 返回: return 别名: alias BEGIN模块相当于C语言中的宏,END模块用来作一些收尾工作。有了require,include ,应该取消BEGIN和END的语法定义。 3.4 运算符 Ruby中的运算符如下: 优先级 能否重载 运算符 描述 最高 Y [] []= 数组下标 数组元素赋值 Y ** 乘冥 Y ! ~ + - 非 位非 一元加 负号 Y * / % 乘 除 模 Y + - 加 减 Y >> << 右移 左移 第 页 Ruby语言入门教程v0.4 Y & (只用于整数) 位与 Y ^ |(只用于整数) 位异或 位或 Y <= < > >= 小于等于 小于 大于 大于等于 Y <=> == === =~ != !~ 各种相等判断(!= !~ 不能重载) && 短路与 || 短路或 .. ... 区间的开始点到结束点 ? : 三元运算符 = %= ~= /= -= += |= &= >>= <<= *= &&= ||= **= 各种赋值 例如:a=5; b+=3( 意思是:b= b+3 ); defined? 检查类型 not 逻辑非 or and 逻辑或 逻辑与 if unless while until 判断与循环 最低 begin/end 定义方法、类、模块的范围 第 页 Ruby语言入门教程v0.4 3.5 标识名和变量的作用域 Ruby的标识名用来指向常量,变量,方法,类和模块。标识名的首字符用来帮助我们确定标识所指向内容的作用域。一些标识名,就是上面所示的关键字,不能用来当作常量,变量,方法,类或模块的名字。 Ruby的标识名区分大小写。 Ruby使用一个约定来帮助它区别一个名字的用法:名字前面的第一个字符表明这个名字的用法。局部变量、方法参数和方法名称应该用一个小写字母开头或者用一个下划线开头;全局变量用美元符作为前缀($);而实例变量用@开头;类变量用两个@开头;类名、模块名和常量应该用大写字母开头。 词首字母后面可以是字母、数字和下划线的任意组合;@后面不可以直接跟数字。 Ruby程序代码现在是用7位ACSII码来表示,通过语言扩展来支持EUC, SJIS或UTF-8等8位编码系统。Ruby 2.0版本将支持16位的Unicode编码。 3.6 类库 Ruby像C++一样,有许多类库可以供你使用,其中的I/O库很完善。前面我们使用了 puts 和 print ,你一定注意到它们并不是关键字,为什么能够直接使用? 一门编程语言,A)关键字可以直接使用;B)还有其它常用的应用程序,我们将它们放在一个专门的目录下,称为类库(许多类的仓库)。如果当前程序要用到类库中某个程序已经定义好的类、方法,就应该使用 require 或者 include 将类库程序名包含在当前程序中;C)从父类继承得到的方法可以直接使用。 I/O 就是 输入/输出,这是Ruby语言Kernel模块的方法,Mixin在根类Object中的 第 页 Ruby语言入门教程v0.4 。 puts把它的所有参数写出来,每一个参数结束都加入一个换行符,print也写出它的参数,不过没有换行。你可以指明输出到一个文件,不说明,则一般输出到显示器。 还有一个常用的输出方法是printf,它按格式输出参数(就像C的printf)。 printf "Number: %4.3f, String: %s", 7.8, "hi!" 运行结果: Number: 7.800, String: hi! 这个例子中,格式字符串"Number: %4.3f, String: %s" 告诉printf用一个浮点数(总共允许4位,小数点后3位)和一个字符串来代替。printf 和 print 一样,不主动换行,换行可以用“\n”。 介绍了三个输出方法,再介绍一个输入方法:gets ,它从你的程序的标准输入流中返回一行。一般用来从键盘或文件读入一行数据。 3.7 数据类型 Ruby数据类型有数字,字符串,数组,哈希表,区间,正则表达式。 数字分为整数型(1,0,75 ,1e3),浮点型(2.4 ,7.0 ,0.99)。浮点型数据小数点后必须跟数字( 1.e3 不可以,1.1e3可以)。数字可以有前缀:0表示八进制, 0x表示十六进制, 0b表示二进制(0724,0x5AC4,0b11101)。 字符串是在‘ ’(单引号)、 “ ”(双引号)之间的代码。 数组的下标从0开始。Ruby的数组和其它语言不同,数组的每个元素可以是不同的类型:[ 2.4, 99,“thank you”,[ a, b ,c ] ,78 ]。 第 页 Ruby语言入门教程v0.4 区间:1..5 表示1,2,3,4,5 ; 1...5表示1,2,3,4 。 3.8 赋值和关系运算符 Ruby基本的赋值用“ = ”来完成,就像 E3.8-1.rb 如下示例:(在不产生歧义的地方,我用 >>表示答案) a = 1 ;b = 2 + 3 >>a=1 ,b=5 a ,b = b ,a >>a=5 ,b=1 a = b = 1 + 2 + 3 >>a=6 ,b=6 a = (b = 1 + 2) + 3 >>a=6 ,b=3 x = 0 >>x=0 a,b,c = x, (x+1), (x+2) >>a=0 ,b=1,c=2 Ruby的关系运算符比Java更加复杂,看例子 E3.8-1.rb: ==(等于) != (不等于) 比较两个对象的值是否相等 ,返回 true,flase a=1; b=1.0; a==b >>true eql? 比较两个对象的值、类型是否相等,返回 true,flase a=1; b=1.0; a.eql?(b) >>flase (a为整数型,b为浮点型) equal? 比较两个对象在内存中地址是否相同,返回 true,flase a=1.0; b=1.0; a.equal?(b) >>flase a=1.0; b=a ; a.equal?(b) >> true 第 页 Ruby语言入门教程v0.4 <=> 比较两个对象的大小,大于、等于、小于 分别返回1,0,-1 "aab" <=> "acb" >> -1 (第二个a的ASCII码小于c) [5] <=> [4,9] >> 1 (第一个元素 5>4) === 右边的对象是否在左边区间之内,返回 true,flase puts (0..9)=== 3.14       >>true puts ('a'..'f')=== 'c'       >> true =~(匹配) !~ (不匹配) 用来比较是否符合一个正则表达式,返回 true,flase <= < > >= 小于等于 小于 大于 大于等于 3.9 条件判断语句 判断条件是否相等用“==”,注意不要写成“=”。 一. 单行 if(如果) 语句 1) if 条件 then 语句1; 语句2 ; 语句… end 2) 单条语句 if 条件 二. 多行 if 语句 if 条件 语句1; 语句2 ; 语句… 第 页 Ruby语言入门教程v0.4 elsif 条件 语句1; 语句2 ; 语句… else 语句1; 语句2 ; 语句… end 三. unless(除非) 条件语句: unless 条件 = if not (条件) 四. case分支条件语句 E3.9-1.rb case 对象 when 可能性1 语句1; 语句2 ; 语句… when 可能性2 语句1; 语句2 ; 语句… when 可能性… 语句1; 语句2 ; 语句… else 语句1; 语句2 ; 语句… end 例:x=3 case x when 1..2 print "x=",x,";在 1..2中" when 4..9, 0 print "x=",x,";在4..9,0中,或是0" else print "x=",x,";其它可能" end 结果:x=3;其它可能 第 页 Ruby语言入门教程v0.4 3.10 循环语句 一. while(当…) 循环 while 条件 语句1; 语句2 ; 语句… end 二. 单行 while 循环 单条语句 while 条件 三. until(直到…) 循环 我们想输出数字1到9,看程序 E3.10-1.rb,E3.10-2.rb : a=1 while a <10 print a," " a=a+1 end >>1 2 3 4 5 6 7 8 9 a=1 until a >=10 print a," " a=a+1 end >>1 2 3 4 5 6 7 8 9 一边是while a <10,一边是until a >=10,其它代码都一样,结果也一样。从这两个小程序可以看出: until 条件 = while not (条件) 四. for…in 循环 第 页 Ruby语言入门教程v0.4 for 变量 in 对象 语句1; 语句2 ; 语句… end 对象可以是数组,区间,集合…, 看程序 E3.10-3.rb: # E3.10-3.rb for i in 1..9 print i," " end >>1 2 3 4 5 6 7 8 9 五.break , next & redo & retry 在循环体内,如果遇到: break ,跳出当层循环; next ,忽略本次循环的剩余部分,开始下一次的循环; redo ,重新开始循环,还是从这一次开始; retry ,重头开始这个循环体。 看程序 E3.10-5.rb 。 六. 求50以内的素数。 # E3.10-4.rb 求50以内的素数 for i in 2..50 #50以内 f=true #起始假定每个数都是素数 for p in 2...i #比自身小的正整数(1和自身除外) if i%p==0 #如果能整除 第 页 Ruby语言入门教程v0.4 f=!f #那么这个数不是素数 break #并且跳出这层循环 end # if 结束 end #内层循环结束 print i," " if f #如果这个数保持起始假定,则打印 end #外层循环结束 >>2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 E3.10-6.rb 这个小程序不是最优化的,你可以复制到自己的编辑器内,试着反复重构优化。 七. times , upto , downto , each , step 3.times { print "Hi!" } >>Hi!Hi!Hi! 1.upto(9) {|i| print i if i<7 } >>123456 9.downto(1){|i| print i if i<7 } >>654321 (1..9).each {|i| print i if i<7} >>123456 0.step(11,3) {|i| print i } >>0369 看程序 E3.10-7.rb 。 3.11 异常与线程 与Java中的try…catch…finally…throw 相对应, Ruby中用begin/end …rescue…ensure … raise 来处理异常,retry可以用在rescue中。 第 页 Ruby语言入门教程v0.4 可以只用rescue或是ensure,两者都使用时,rescue必须在ensure前。 如果你初识Ruby,不必理会异常与线程。Java程序员用异常来保证文件和数据库连接的关闭;至于线程,只是在考认证时才用到。 3.12 一个综合小练习 还是求50以内的素数,尽可能地用到本章更多的语法,看程序 E3.12-1.rb 。 $arr.push(num)的含义是:将素数num作为数组的一个元素加入到$arr中。你很容易地理解了这个小程序,说明本章内容你已经熟练掌握了。你如果不做程序员,有点儿遗憾。 第 页 Ruby语言入门教程v0.4 第四章 一切都是对象 4.1 两种思维方式 人们起初使用计算机来进行科学计算,比如说:计算级数和,计算积分值。那时,程序要处理的都是带小数点的数字。后来,人们要处理文本,有点麻烦,好在文字也可以转换成数字。这两个时期,编写程序的思想是:一个步骤,一个步骤地告诉计算机如何做,做完一大段步骤,就算完成了一个功能模块。 再后来,人们希望计算机能应用在管理中。比如说:机场管理。一个大都市的民航机场,每天有上千架飞机起落,乘客上万,行李、包裹无数,乘务、地勤人员上千,安检信息上万,气象信息上万……这样百万、千万的数据要及时处理,靠旧的编程思维是无法实现的。 为了应付越来越复杂的管理应用,人们转变编写程序的思想: (1). 将一架飞机看作飞机类事物的一个具体实例,将一座塔台看作塔台类事物的一个具体实例,将一名乘客看作乘客类事物的一个具体实例…… (2). 一个具体实例有变化的时候,就自己主动传递消息给相关联的具体实例; (3). 相关联的具体实例收到消息后,根据之前定好的策略,作出应有的反应(回应,转发……)。 初期的编程思想是:以“如何做”为指导来编写代码。这时期的编程语言叫过程语言,语句以判断和循环为主。代表语言是FORTRAN和C。 现在的编程思想是:以“谁将被影响”为指导来编写代码。叫面向对象的编程语言,以类为模块。代表语言是C++ 和Java。 第 页 Ruby语言入门教程v0.4 4.2 对象 英文Object ,计算机业界现在已经习惯翻译为“对象”;口语化一些,中文的意思就是“事物”。 “事物”这个词有点抽象,你当然可以具体到人,或是具体到交通工具。人可以再具体一些,学生?工人?如果是学生,叫什么名字? 事物 人 交通工具 工人 学生 每个事物都有一些特点,人有身高,体重,在程序中我们称之为属性;还可以有一些行为,人要吃饭,睡觉,在程序中我们称之为方法。 学生是人,自然有身高,体重,自然要吃饭,睡觉。如果你把人看作一类事物,把学生看作一类事物;那么,人是父类型,学生是子类型。子类型从父类型自然得到属性、方法,我们称之为继承。 学生要考试,工人不要;工人拿工资,学生不拿(一般而言)。同一个父类,不同的子类有不同的行为和状态,我们称之为多态。 人们编写程序,也就是在描述一类事物的特点(属性)、行为(方法)。有时候是模拟描述自然界中已有的一类事物,还有时候是创造地描述自然界中没有的一类事物。 当人们决定了代码世界中一类事物的属性、方法,在代码世界中,这类事物的属性、方法只有定义代码的人知道,其它的类是不知道的。这就是封装。 封装、继承、多态是面向对象编程的三个本质特征。 (人们可以决定代码世界中一类事物的属性、方法,当然可以修改代码世界中一类事物的属性、方法,而且可以委托其它的类来修改,甚至删除。这是动态语言超越静态语言之处。由于代码是一直运行着,与其它代码一直交互着,修改 第 页 Ruby语言入门教程v0.4 、删除应该慎重,避免产生副作用)。 4.3 封装 让我们来定义一个类,类名是Person,类名、模块名、常量名,首字母要大写;属性有姓名@name、年龄@age、国籍@motherland,实例变量用@开头; 方法有一个,叫talk,变量名、参数名和方法名应该用一个小写字母开头或者用一个下划线开头,看程序 E4.3-1.rb 。 class Person def initialize( name, age=18 ) @name = name @age = age @motherland = "China" end #初始化方法结束 def talk puts "my name is "+@name+", age is "+@age.to_s if @motherland == "China" puts "I am a Chinese." else puts "I am a foreigner." end end # talk方法结束 attr_writer :motherland 第 页 Ruby语言入门教程v0.4 end # Person类结束 p1=Person.new("kaichuan",20) p1.talk p2=Person.new("Ben") p2.motherland="ABC" p2.talk >>my name is kaichuan, age is 20 I am a Chinese. my name is Ben, age is 18 I am a foreigner. @age.to_s的含义是:将数@age转换为字符串。 initialize是初始化方法,相当于Java的构造器。参数age有一个缺省值18,可以在任何方法内使用缺省参数,而不仅仅是initialize。如果有缺省参数,参数表必须以有缺省值的参数结尾。 attr_writer :motherland 相当于 def motherland=(value)   return @motherland =value end  attr_ reader :motherland 相当于 def motherland   return @motherland end  这就是我们熟悉的get 和set 方法的简写形式。你不熟悉也不重要。 attr_accessor :motherland 相当于attr_reader:motherland; attr_writer :motherland 这个Person类可以talk,如何实现的?写Person类的人知道,其它的类不知道,只是调用而已。封装完成了隐藏实现。 第 页 Ruby语言入门教程v0.4 4.4 继承 如果我们要写一个学生类,他当然有姓名、年龄、国籍,他也可以talk,但是应该表明身份是学生。看程序 E4.4-1.rb ,接着上一节的代码,添加如下: class Student < Person def talk puts "I am a student. my name is "+@name+", age is "+@age.to_s end # talk方法结束 end # Student类结束 p3=Student.new("kaichuan",25); p3.talk p4=Student.new("Ben"); p4.talk >>I am a student. my name is kaichuan, age is 25 I am a student. my name is Ben, age is 18 用“ < ”表示Student类是 Person类的子类。Person类的一切,Student类都能继承。但是Student类重写了talk方法,所以我们看到了不同的运行结果。子类继承父类的时候,除了重写方法,也可以添加一些新的方法,或是增强父类的方法(用关键字super指明)。 现在说一说new方法。Person类没有定义new方法,为什么生成Person类的具体实例要用new? Ruby语言已经定义了一个类Object,如果你在定义新类的时候,没有指明新类的父类,那么,Ruby解释器认为,新类的父类是Object类。类Object含有new方法、initialize方法…只要你不重写这些方法,你就自然在使用类Object的方法。 从这里,我们发现一个有趣的事实:你写一个类的时候,是在创造一类事物的蓝图;当你new的时候,一个实例就按照蓝图生成了。 一个实例生成了,又一个实例生成了…他们或许是同类型的,或许不是同类型的,或许是有亲缘关系的。无数的实例在代码世界中交互、缠结,忽生忽死,无休无止… 第 页 Ruby语言入门教程v0.4 蓝图早已设计好了,new的时候就是出生的时刻,那么,何时消亡呢?这里没有C++的析构函数,也没有Java的finalize() 方法,Ruby语言内建了一个比Java更灵巧的垃圾收集器,当某个实例不再与其它代码交互了,垃圾收集器就回收它占用的系统资源,这个实例自然也就不存在了。垃圾收集器是一段代码,它作它的工作,自动地、不知疲倦地随着系统一同运作,并无自己的喜恶。 4.5 多态 不同的子类继承一个父类,不仅子类和父类的行为有变异,而且子类彼此的行为也有差异,这就是多态。看程序 E4.5-1.rb ,接着4.3节的代码,添加如下: class Worker < Person def talk puts "I am a worker. my name is "+@name+", age is "+@age.to_s end # talk方法结束 end # Worker类结束 p5=Worker.new("kaichuan",30);p5.talk p6=Worker.new("Ben");p6.talk >> I am a worker. my name is kaichuan, age is 30 I am a worker. my name is Ben, age is 18 Worker类与Student类同样继承自Person类,亲缘关系是兄弟,当他们talk时,能准确表明自己身份,因为他们都重写了各自的talk方法。 这儿的代码没有很好地说明多态性,因为Ruby是弱类型语言,只有重写(override),没有其它语言具有的严格意义上的重载(overload)。Ruby语言有自己的单例方法与单态模式,还有模块插入(mixin),后面会深入探讨Ruby语言的面向对象特征。 第 页 Ruby语言入门教程v0.4 小跋 编程语言,教材里称之为程序设计语言,这本书中,将“程序设计”弱化为“编程”,根源于实践工作中的体会。几年前的某个晚上,在海轮上过夜,当明月无声地升起,我有一种特别的感觉,不是感慨万千,而是心中空空洞洞,一无所想。甲板上的同伴说些什么,我已经听不见了,不因为海浪的颠簸起伏,也不因为周围的一望无际,我无法言语。“大哉,斯矣!” 夜色已深,霓虹消失,浮华散尽,一切都回归本来面目。我在思索,我们应该把肩膀降得低一些,再低一些,好让后面的人踏着向前。明天,太阳照常升起,一切新生力量又将开始新的一天。 我努力使这本书面向没有编程经验的人,可是书中太多的痕迹表明我常常以Java的习惯在思考问题,好在多一些角度思考问题并不是坏事。书中许多内容来自网络,我已经没法一一历数出处,再次感谢你和他——生活在网络的人们,再次感谢这个网络世界。 2007年1月16 第 页 Ruby语言入门教程v0.4 欢迎继续阅读 第五章 5.1 为什么是Ruby? 5.2 Ruby会长久么? 5.3 详解变量—— 动态类型、弱类型 5.4 蓝图可以改变吗? ——动态语言 第六章 深入面象对象 重载?重写 增强父类方法 类变量、类方法、实例变量 第 页 Ruby语言入门教程v0.4 单例方法与单态模式 访问控制 第七章 模块 糅和(mixin) 与多重继承 命名空间 require和 include  第八章 再说数组、字符串 正则表达式 迭代器、块、闭包 第九章 元编程 第 页 Ruby语言入门教程v0.4 第五章 5.1 为什么是Ruby? 现在软件生产的代表语言是Java。但Java已老,在主流市场,虽然它还会将继续存在许多年。 为什么说Java已老?很怀念Pascal的严谨、优美与高效。Java也一样,是静态语言,沉稳的同时注定了笨重,不善腾挪;而且Java是强静态语言,在需要简略的地方,依然沉稳笨重。仿佛一个绅士,在宴会大厅中彬彬有礼,在厨房里彬彬有礼,在卧室里仍然彬彬有礼。灵气沾不上Java,神来之笔沾不上Java。这一切,注定了Java与软件的快速开发无缘。 为什么不是C++,C#?从C++开始,C系列语言已经走上一条不归路。C++不仅兼容C,而且囊括了模板、范型等特性,包罗万象。无论是系统调用、网络开发、数据库操作都能显试身手,可是程序员很难掌握这些,即使想熟练应用其中某一方面也不容易。一个软件,一个语言,或是一个人,当他(它)想要得到整个世界的时候,危机已经埋下了。(Java已经支持范型;支持不完全的元编程——元数据操作只是元编程的子集。强静态语言支持元数据操作?为什么置自己短处而不顾,硬是要用铁棒来缝衣服,难道就为了成为最大最全?) 当我们厌倦了静态语言的时候,当我们饱受大象思维折磨的时候,Ruby浮现出来,灵巧,快速。 5.2 Ruby会长久么? Ruby会长久么?这很难回答。重要的是,编程语言将向动态回归,命令式语言将与函数式语言融合。终究有一天,编程语言完全智能化,人们用自然语言来编程。而Ruby有可能在编程语言的智能化发展道路上起到承上启下的作用。 Ruby灵巧,快速,但其实并不简单。 第 页 Ruby语言入门教程v0.4 Ruby中实现一个小功能,可以有3种甚至4种完全不同的思路与方法,因为Ruby在语法层次实现了冗余,但是这样一来: 1).程序员深入掌握Ruby变得不很容易; 2).程序员们相互读懂代码也很难; 3).软件生产是一种大规模地、群体合作的行为。许多软件公司有自己的编码规范,促使员工编码风格统一,以便于A)程序解耦重构、B)代码重用、C)人员流动后项目如期推进。Java撇下C++,成为软件工业的支柱语言,正是得力于此。Ruby灵巧,快速,千变万化,没有统一风格,难于解耦,在目前,自然不适合工业生产。 在数据库设计中,讲究最小相容集,有时也有些许冗余,那是为了效率。而Ruby在语法层次实现冗余,显然不是为了效率,那么是为了强壮?为了容错?Erlang 语言也实现了高网络并发与容错,那是编译内核(或解释内核)的职责。不需要把太多相互可以替代的语法规则抛给语言使用者。 第 页

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 20 金币 [ 分享文档获得金币 ] 1 人已下载

下载文档