`
javatoyou
  • 浏览: 1016497 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

Ruby系列学习资料(三)

 
阅读更多
三、OOP in Ruby
Ruby的所有元素与OOP语言关系更密切,如对象封装,数据隐藏,方法的多态和覆写,类的层次和继承。 它更进一步地添加了有限制的元类特征,单态方法,模块和混插。
类似的概念在其它OOP语言内使用了其它的名字,但是相同名字的概念在语言之间也有些差别。这个部分详尽阐述OOP的这些元素在Ruby中的理解和用法。

1、对象

在Ruby中,所有的数字,字符串,数组,正则表达式,和更多其它实体都是真正的对象。工作通过执行属于对象的方法来完成:
3.succ
# 4

"abc".upcase
# "ABC"

[2,1,5,3,4].sort
# [1,2,3,4,5]
someObject.someMethod
# some result
在Ruby中,每个对象都是一些类的实例,类包含方法的实现。对象的类本质上是它的类型:

"abc".type
# String

"abc".class
# String
除了封装它自己的属性和操作之外,Ruby内的对象有个标识。

"abc".id
#
53744407


2、内建类

在Ruby的类层次中预定义有超过30个的内建类。像大多数其它的OOP语言,Ruby不允许多重继承,但是那并不会减少它的强大。现代面向对象的语言经常允许单根继承模式。Ruby支持下一节讨论的模块和混插。它也实现了对象的ID,来支持对永续性,分布性,和可再配置对象的实现。
要从现有类创建对象,典型地是使用new方法:
myFile = File.new("textfile.txt","w")
myString = String.new("this is a string object")
然而,这并不总是被明确要求的,像这儿显示的:
yourString = "this is also a string object"
aNumber = 5
变量被用于持有对对象的引用。像先前提到的,变量本身没有类型,它们不是对象本身;它们只对象的简单引用。这儿个例子:
x = "abc"
它的例外是那些小的,固定不变的,内建类的对象,如Fixnum,被直接复制到它们的变量中。(这些对象没有指针大,并且以这种方式更高效地处理它们。)在这种情况下,赋值是对对象的拷贝,并且堆(内存分配区域)不再被使用。
变量赋值会引起对象引用被共享:
y = "abc"
x = y
x
# "abc"
x = y 被执行之后,变量x和y两者引用同一个对象:
x.id
# 53732208
y.id
# 53732208
如果对象是可变的,对一个变量完成修改操作将会影响到另一个:
x.gsub!(/a/,"x")
y
# "xbc"
Reassigning one of these variables has no effect on the other, however:
x = "abc"
y
# still has value "xbc"
一个可变对象可以使用freeze方法变成不可变的:
x.freeze
x.gsub!(/b/,"y")
#
error
Ruby内的符号(symbol)通过ID引用变量而不是通过引用。当我们说:x时,与我们说x.id(你在前面看到的)是一样的。在符号内一个冒号相当于一个标识符结果;如果这个标识符不存在,则创建它。在其它用法中,当我们提到而不是使用一个标识符时(经典的”使用与提到”之间的差别),符号也可以被使用;例如,具体方法method_missing,在方法没有被找到时调用,接受一个与未知方法相对应的符号。所有Symbo对象都有一个方法叫id2name,它返回相应于标识符名称的字符串。这儿是例子:
Hearts
= :Hearts
# This is one way of assigning
Clubs
= :Clubs
#
unique values to constants,
Diamonds
= iamonds #
somewhat like an enumeration
Spades
= :Spades
#
in Pascal or C.


print Hearts.id2name
# Prints "Hearts"


3、模块和混插

来自类祖先的许多内建方法都是有利用的。要特别注意的是Kernel内的方法被混插到了Object超类中;因为Object是普遍存在的,所以从Kernel中添加给它的方法当然也是普遍存在的。这些方法形成Ruby非常重要的部分。
术语模块和混插(mixin)几乎是同义词。模块是方法和常量的集合,用于扩展Ruby程序。它也可被简单地用于名字空间的管理,但是模块大多数的普通用法是它对类的混合插入特征(使用include)。在这种情况下,它被用做一个混插(mixin,这个术语借用于Python,有时候被写成mix-in,但我写成一个单独的单词)。
为名字空间管理而使用模块的一个例子是经常使用的Math模块。例如,要使用pi的定义,必须包括Math模块;你要以像简单地使用常量那样使用Math:I。
混插(mixin)提供了获取多重继承优点而不处理所有难点的一种途径。它可以被认为是多重继承的一个有限制的形式,但是语言的创始者Matz称它为"带实现共享的单继承"。
注意,include附加(模块的)名字空间特征给当前作用域。extend附加模块的方法给一个对象。在include内,模块的方法变成可用的实例方法;在extend内,它们变成可用的类方法。
我们应该提一下,load和require不是真正与模块有联系,而是指非模块的Ruby和二进制源(静态的或动态地被加载)。Load操作本质上是读一个文件并将它插入到源文件的当前位置,以便它的定义在那个位置是可用的。Require操作与load类似,但是如果它已经加载了一个文件,它就不会再次加载它。


4、创建类

Ruby有众多的内建类,Ruby程序内也可以定义额外的类。要定义一个新类,使用下面结构:
class ClassName

# ...
end
类的名字本身是个全局常量,所以它必须以大写字母开头。类定义可以包含类常量,类变量,类方法,实例变量和实例方法。类数据对类的所有对象都是有效的,反之,实例数据只对一个对象有效。这儿是个例子:
class Friend

@@myname = "Fred"
#类变量

def initialize(name, sex, phone)

@name, @sex, @phone = name, sex, phone
# 实例变量

end

def hello
# 实例方法

print "Hi, I'm #{ @name} .n"

end

def Friend.our_common_friend
# 类方法

print "We are all friends of #{ @@myname} .n"

end
end
f1 = Friend.new("Susan","F","555-0123")
f2 = Friend.new("Tom","M","555-4567")
f1.hello
# Hi, I'm Susan.
f2.hello
# Hi, I'm Tom.
Friend.our_common_friend
# We are all friends of Fred.
因为类级别数据在整个类中是有效的,它可以在类定义的时候被初始化。如果initialize方法被定义,则它保证在一个实例被分配内存之后被正确运行。Initialize方法类似于传递上的构造器概念,但是它不必须处理内存分配。分配的工作在内部由new完成,回收分配的工作明显由垃圾回收器完成。
现在,考虑这个片断,注意getmyvar, setmyvar, 和 myvar=
方法:
class MyClass

NAME = "Class Name"
# 类常量

def initialize
# 当对象被分配时调用。

@@count += 1


@myvar = 10

end

def MyClass.getcount
# 类方法

@@count


# 类变量

end

def getcount
# 返回类变量的实例

@@count
# 类变量

end

def getmyvar
# 实例方法

@myvar
# 实例变量

end

def setmyvar(val)
# 设置@myvar的实例方法。

@myvar = val

end

def myvar=(val)
# 另一种设置@myvar的方式。

@myvar = val

end
end
foo = MyClass.new
# @myvar is 10
foo.setmyvar 20
# @myvar is 20
foo.myvar = 30
# @myvar is 30
这儿,你看到getmyvar返回@myvar的值,并且用setmyvar设置它。(在很多语言的术语中,这些被分别做为getter和setter的引用。) 这儿工作的很好,但它们没有例证出Ruby的做事方式。方法myvar=看起来像被重载的赋值(尽管严格上讲,它不是);setmyvar可以很好地用于替换,但也不最好的方式。
The class 类Module包含了称为attr, attr_accessor, attr_reader, 和attr_writer的方法。它们可以被用于(使用符号(symbol)做为参数)自动地处理对实例变量的访问控制。例如,先前在类定义内命名的三个方法可以由一行来代替。
attr_accessor :myvar
这将创建方法myvar,它返回@myvar的值,和方法myvar=,它能够设置同名的变量。方法attr_reader和attr_writer分别地创建一个属性的只读和只写版本。有关更多细节,可看Ruby参考手册。
在类的实例方法内,伪变量self可按需要使用。它只是对当前接收者(实例方法被调用的对象)的引用。
修饰方法private, protected, 和public可以被用于控制类内方法的可见性。(实例变量总是private 的,并且它不可以从类的外部被访问,除了使用存取器手段。) 每个修饰方法每个修饰方法都接受一个符号(symbol)如:foo做为一个参数,如果省略参数,则修饰方法被应用于类内所的后续定义:
class MyClass

def method1

# ...

end

def method2

# ...

end

def method3

# ...

end

private :method1

public
:method2

protected :method3

private

def my_method

# ...

end

def another_method

# ...

end
end
在这个例子中,method1将是private的, method2将是public的,method3将是 protected的。因为private方法没有参数,所以my_method和another_method两个将是private的。
public访问级别是self-explanatory;在访问和可见性上没约束。private 级别意味着方法只可以由类内或它的子类访问,并且只能由self(明显的或暗中的)做为接收者以函数形式调用。protected级别意味着只可以从它的类内调用,但是不像private方法,它可以由不是self的接收者调用,如同一个类的另一个实例。
一个类内的方法定义缺省可见性是pubic。除了实例初始化方法initialize,它的private的因为它从new方法中被调用。顶层的方法定义缺省也是public的;如果它们是private,它们则只能以函数形式被调用(例如,Object内定义的方法)。
Ruby的类本身也是对象,是元类Class的实例。Ruby类总是具体的;它没有抽象类。可是,如果你真需要话,理论上Ruby内是可以实现抽象类的。
类Object是层次的根。它提供内建Kernel模块的所有方法。
要创建从另一个类继承的类,它可这样定义:
class MyClass < OtherClass

# ...
end
除了使用内建方法之外,你自然可以定义你自己的方法,也要以引用和覆写现有的方法。当你以现有方法的名字定义一个方法时,先前的方法被覆写。如果方法需要调用它已覆写了的"双亲"的方法(经常发生的),这时可以使用关键字super。
操作符重载严格上不是一个OOP特征,但对于C++等程序员则很熟悉它。因为Ruby内的大多数操作符只是一个简单的方法,所以这些操作符可以被重载或由用户定义的类定义则是很正常的事。为一个现有类覆写操作可能很少见,但对一个新类定义操作符则是很平常的。
为方法创建别名同义词是可行的。使用下面语法(用于类内定义):
alias newname oldname
参数的数量与原有名字是一样的,并且以相的方式调用。


5、方法和属性

前一节,方法被用于简单的类实例和变量中,是通过用句点来分离接收者和方法 (receiver.method)。这种情况下方法的名字就像个句法,句点被省略了。方法可以接受参数:
Time.mktime( 2000, "Aug", 24, 16, 0 )
因为方法调用返回对象,方法调用典型地可被链接或堆叠:
3.succ.to_s

/(x.z).*?(x.z).*?/.match("x1z_1a3_x2z_1b3_").to_a[1..3]

3+2.succ
注意累积的表达式若不是那个特定方法支持的类型,会出现问题。特别地,一些方法返回nil而不确定的条件,这会让任何接受那个结果方法失败。
某些方法可以被传递块。所有的迭代器都可以这样,而不管是内建的还是用户自定义的。被传递的块通常是do-end
分享到:
评论

相关推荐

    计算机精品学习资料大放送

    最新最全Ruby、Ruby on Rails精品电子书等学习资料下载 数据库管理系统(DBMS)精品学习资源汇总:MySQL篇 | SQL Server篇 | Oracle篇 ActionScript、Flex、AIR等RIA技术相关资料下载汇总 最强HTML/xHTML、CSS精品...

    Ruby On Rails开发从头来系列教程(chm)

    摘要:一直想尝试Ruby On Rails,但是因为对apache,mysql都不熟,对Rails的环境搭建更是没信心,所以一直没有开始,从知道了InstantRails后,终于在windows上搭建了Ruby On Rails开发环境,开始了Rails的学习。...

    Ruby语言教程&案例&相关项目资源

    这篇文章是一份全面而深入的Ruby语言学习资源指南,旨在为那些想要学习Ruby编程的开发者提供清晰的学习路径和实践机会。通过这篇文章,您将了解到Ruby语言教程、案例以及相关项目资源的丰富内容,从而能够系统地掌握...

    Matlab系列--学习各种语言的(c c++ java Python ruby MATLAB lingo math.zip

    Matlab系列--学习各种语言的(c c++ java Python ruby MATLAB lingo math

    ruby书籍1

    很全的ruby书籍系列之一,希望对大家学习ruby有帮助:)

    Ruby中使用SWIG编写ruby扩展模块实例

    在使用ruby/rails的过程中,确实发现有时性能不尽人意,如生成一个拥有600项的item的3层树形结构目录要花去20ms,为提高性能在学习用c/c++写ruby模块的过程中,认识了swig,rubyInline等一系列帮助编写c/c++来提升...

    gdi-ruby:为GDI设计的为期5周的Ruby编程课程

    Ruby简介 该课程的幻灯片可以在查看 这是Ruby入门课程。 所有材料均由Cheri Allen和Heather Moore撰写... 通过这五个课程系列,您将全面了解Ruby的编程基础。 我们将使用Interactive RuBy shell; 编写使用循环,条件,

    sketchup-rubyscript-tutorials:Google SketchUp 的 Ruby 脚本教程。 对于那些渴望创建一些常规计算几何的人。 并学习Ruby。 也许也学习编程

    Sketchup-rubyscript-教程这个存储库计划成为我的 rhino-pythonscript-tutorial 系列的 Sketchup Ruby 脚本实现。

    Ruby CGI 编程

    接下来,让我们花点时间来学习Ruby的CGI编辑。 网页浏览 为了更好的了解CGI是如何工作的,我们可以从在网页上点击一个链接或URL的流程: 1、使用你的浏览器访问URL并连接到HTTP web 服务器。 2、Web服务器接收到请求...

    原始Ruby前功

    您如何创建一系列数字? 您如何将范围转换为数组,以便可以对其进行迭代? 要求: 不要使用任何其他Ruby库。 您必须构建一种可以验证数字是否为质数的方法。 require 'math' ,只需背负其素数的实现即可。先进的...

    code_quizzer, 使用 ruby JavaScript Rails 和Bash编程实践问题.zip

    code_quizzer, 使用 ruby JavaScript Rails 和Bash编程实践问题 CodeQuizzes关于站点在 ,Rails,JavaScript,Bash,git中包含一系列编程实践问题。 等等 !当我学习编程并决定创建CodeQuizzes作为我的第一个 Rails ...

    Ric.Shreves.PDF文字版.pdf

    最新最全Ruby、Ruby on Rails精品电子书等学习资料下载 数据库管理系统(DBMS)精品学习资源汇总:MySQL篇 | SQL Server篇 | Oracle篇 平面设计优秀资源学习下载 | Flash优秀资源学习下载 | 3D动画优秀资源学习下载 ...

    prime-ruby-v-000

    您如何创建一系列数字? 您如何将范围转换为数组,以便可以对其进行迭代? 要求: 不要使用任何其他Ruby库。 您必须构建一种可以验证数字是否为质数的方法。 require 'math' ,只需背负其素数的实现即可。 先进的...

    open cv 视频学习

    open CV学习视频 OpenCV是一个基于BSD许可(开源)发行的跨...它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。

    prime-ruby-online-web-prework

    您如何创建一系列数字?您如何将范围转换为数组,以便可以对其进行迭代?要求:不要使用任何其他Ruby库。您必须构建一种可以验证数字是否为质数的方法。 require 'math' ,只需背负其素数的实现即可。先进的考虑一下...

    程序员为什么还要刷题-rspec:[Ruby,tdd,rspec]

    学习目标 解释单元测试的目的和好处 描述 TDD 及其重要性 解释什么是 RSpec 比较和对比expectations和matchers 比较和对比常见的 RSpec 术语,包括"describe" 、 "it" 、 "context" 、 before(:each) 、 before(:all...

    prime-ruby-online-web-sp-000

    您如何创建一系列数字?您如何将范围转换为数组,以便可以对其进行迭代?要求:不要使用任何其他Ruby库。您必须构建一种可以验证数字是否为质数的方法。 require 'math' ,只需背负其素数的实现即可。先进的考虑一下...

    prime-ruby-onl01-seng-pt-052620

    您如何创建一系列数字? 您如何将范围转换为数组,以便可以对其进行迭代? 要求: 不要使用任何其他Ruby库。 您必须构建一种可以验证数字是否为质数的方法。 require 'math' ,只需背负其素数的实现即可。 先进的...

    计算机视觉+机器学习+OpenCV

    [1] 它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。 该开发包合集,是笔者花了2天时间,从OpenCV官网...

    HeadFirst系列之:深入浅出Rails(中文版)高清完整PDF

    你甚至可以舒适并熟练地使用Ruby——但你是在Web编程的上下文中去做这些,而不是另一个无聊的“Hello,World!”。 本书的特别之处 我们认为你的时间如此宝贵以至于不应该花费在为新概念伤脑筋上面。《深入浅出Rails...

Global site tag (gtag.js) - Google Analytics