首页 | 新闻 | 新品 | 文库 | 方案 | 视频 | 下载 | 商城 | 开发板 | 数据中心 | 座谈新版 | 培训 | 工具 | 博客 | 论坛 | 百科 | GEC | 活动 | 主题月 | 电子展
返回列表 回复 发帖

认识六个被误解的 Ruby 特性(1)

认识六个被误解的 Ruby 特性(1)

如果您是一名 C++ 程序员且需要在 Ruby 环境中工作,那么您有一些功课要做。本文讨论了 Ruby 新手可能会误解的六个 Ruby 特性,特别是当他或她来自一个类似但又不太相同的环境,比如 C++:
  • Ruby 类层次结构
  • Ruby 中的单例方法
  • self 关键词
  • method_missing 方法
  • 异常处理
  • 线程
注意:本文中所有的代码均进行测试,且基于 Ruby 版本 1.8.7。
Ruby 中的类层次结构Ruby 中的类层次结构会很棘手。创建一个 Cat 类型的类并开始探讨其层次结构(参见 )。
清单 1. Ruby 中的隐式类层次结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
irb(main):092:0> class Cat
irb(main):093:1> end
=> nil

irb(main):087:0> c = Cat.new
=> #<Cat:0x2bacb68>
irb(main):088:0> c.class
=> Cat
irb(main):089:0> c.class.superclass
=> Object
irb(main):090:0> c.class.superclass.superclass
=> nil
irb(main):091:0> c.class.superclass.superclass.superclass
NoMethodError: undefined method `superclass' for nil:NilClass
        from (irb):91
        from :0




Ruby 中的所有对象(甚至用户定义的对象)都是 Object 类的后代,这在清单 1 中清晰可见。这与 C++ 是鲜明的对比。这一点也不像普通数据类型,例如 C/C++ int 或 double。清单 2 显示了整数 1 的类层次结构。
清单 2. 整数 1 的类层次结构
1
2
3
4
5
6
7
8
irb(main):100:0> 1.class
=> Fixnum
irb(main):101:0> 1.class.superclass
=> Integer
irb(main):102:0> 1.class.superclass.superclass
=> Numeric
irb(main):103:0> 1.class.superclass.superclass.superclass
=> Object




到目前为止一切顺利。现在您知道了类本身是 Class 类型的对象。而 Class 最终派生自 Object,如  中所示使用 Ruby 内置的 String 类。
清单 3. 类的类层次结构
1
2
3
4
5
6
irb(main):100:0> String.class
=> Class
irb(main):101:0> String.class.superclass
=> Module
irb(main):102:0> String.class.superclass.superclass
=> Object




Module 是 Class 的基类,但是使用它时有一点要注意,即您不能直接实例化用户定义的 Module 对象。如果您不想深入 Ruby 内部,最好考虑与 C++ 命名空间有类似特征的 Module:您可以定义您自己的方法、常量、等等。您在 Class 中包含了一个 Module,以及 voilà,Module 的所有元素现在会魔法般地成为 Class 的元素。 提供了一个示例。
清单 4. Module 不能进行直接实例化,并且只能与类一同使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
irb(main):020:0> module MyModule
irb(main):021:1> def hello
irb(main):022:2> puts "Hello World"
irb(main):023:2> end
irb(main):024:1> end
irb(main):025:0> test = MyModule.new
NoMethodError: undefined method `new' for MyModule:Module
        from (irb):25
irb(main):026:0> class MyClass
irb(main):027:1> include MyModule
irb(main):028:1> end
=> MyClass
irb(main):029:0> test = MyClass.new
=> #<MyClass:0x2c18bc8>
irb(main):030:0> test.hello
Hello World
=> nil




下面再重申一下重点:当您使用 Ruby 编写 c = Cat.new 时,c 是派生自 Object 的 Cat 类型的一个对象。Cat 类是 Class 类型的一个对象,Class 派生自 Module,而 Module 又派生自 Object。因此该对象及其类型都是有效的 Ruby 对象。
单例方法和可编辑类现在,看一下单例方法。假设您想使用 C++ 建模类似于人类社会的东西。那么您会如何做呢?定义一个名为 Human 的类,然后定义数百万的 Human 对象?这更像是在建模一个呆板的社会;每个人必须具惟一的特征。Ruby 的单例方法在这里就派上了用场,如  所示。
清单 5. Ruby 中的单例方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
irb(main):113:0> y = Human.new
=> #<Human:0x319b6f0>
irb(main):114:0> def y.paint
irb(main):115:1> puts "Can paint"
irb(main):116:1> end
=> nil
irb(main):117:0> y.paint
Can paint
=> nil
irb(main):118:0> z = Human.new
=> #<Human:0x3153fc0>
irb(main):119:0> z.paint
NoMethodError: undefined method `paint' for #<Human:0x3153fc0>
        from (irb):119




Ruby 中的单例方法 是仅与特定对象关联的方法,不能用于一般的类。它们的前缀是对象名称。在  中,paint 方法特定于 y 对象,而且仅限于 y 对象;z.paint 导致一个 “方法未定义” 错误。您可以调用 singleton_methods 来查明一个对象中的单例方法列表:
1
2
irb(main):120:0> y.singleton_methods
=> ["paint"]




不过在 Ruby 中有另一种定义单例方法的方式。看看  中的代码。
清单 6. 创建单例方法的另一种方式
1
2
3
4
5
6
7
8
9
10
11
irb(main):113:0> y = Human.new
=> #<Human:0x319b6f0>
irb(main):114:0> class << y
irb(main):115:1> def sing
irb(main):116:1> puts "Can sing"
irb(main):117:1> end
irb(main):118:1>end
=> nil
irb(main):117:0> y.sing
Can sing
=> nil




还开创了新的可能性,可以添加新方法到用户定义的类和内置的 Ruby 现有类,比如 String。这在 C++ 中是不可能实现的,除非您能够访问您使用的类的源代码。再次观察 String 类()。
清单 7. Ruby 允许您修改一个现有的类
1
2
3
4
5
6
7
8
9
10
11
irb(main):035:0> y = String.new("racecar")
=> "racecar"
irb(main):036:0> y.methods.grep(/palindrome/)
=> [ ]
irb(main):037:0> class String
irb(main):038:1> def palindrome?
irb(main):039:2> self == self.reverse
irb(main):040:2> end
irb(main):041:1> end
irb(main):050:0> y.palindrome?
=> true




清楚地展示了如何编辑一个现有的 Ruby 类来添加您自行选择的方法。这里,我添加了 palindrome? 方法到 String 类。因此 Ruby 类在运行时是可编辑的(一个强大的属性)。
现在您对 Ruby 的类层次结构和单例有了一定的认识,接下来我们来看 self。注意,在定义 palindrome? 方法时我使用了 self。
发现 selfself 关键词的最常见用法可能就是在 Ruby 类中声明一个静态方法,如  所示。
清单 8. 使用 self 声明类的静态方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class SelfTest
   def self.test
      puts "Hello World with self!"
   end
end

class SelfTest2
   def test
      puts "This is not a class static method"
   end
end

SelfTest.test
SelfTest2.test




从  的输出中可以看到(如  所示),没有对象您无法调用非静态方法。该行为类似于 C++。
清单 9. 在没有对象的情况下调用非静态方法时会出错
1
2
3
4
5
6
irb(main):087:0> SelfTest.test
Hello World with self!
=> nil
irb(main):088:0> SelfTest2.test
NoMethodError: undefined method 'test' for SelfTest2:Class
        from (irb):88




在探讨 self 更深奥的用途和含义之前,注意您也可以通过在方法名称前面加上类名来在 Ruby 中定义一个静态方法:
1
2
3
4
5
6
7
class TestMe
   def TestMe.test
       puts "Yet another static member function"
   end
end

TestMe.test  # works fine

返回列表