参考手册:标准库——内部类

哈希表(也叫散列表)的类.通过哈希表,您可以将一个任意类型的对象同另一个任意类型的对象联系起来.可以使用下列哈希表表达式来生成哈希表.

{a=>b, ... }

通常使用Object#hash方法来计算哈希表的值,而使用Object#eql?方法来判定索引是否相同.

若用作索引的对象的内容发生了变化,且hash方法的返回值也有所不同时,将无法取出哈希表中的值.所以Array、Hash等的实例并不面向索引对象本身. 例如,若将字符串作为索引时,将先拷贝该字符串,然后把拷贝设为只读(freeze),最后将该拷贝用作索引.若想更改索引字符串的内容时,将引发TypeError异常.
超类:

  * Object

包含的模块:

  * Enumerable

类方法:

Hash[key,value,...]
Hash[hash]

  生成新的哈希表.使用第一种形式时,参数的个数必须是偶数.(奇数位参数是索引,偶数位参数是元素值).

  使用第二种形式(将一个哈希表对象指定给参数)时, 将生成并返回一个与指定哈希表相同的全新的哈希表.(生成的哈希表的默认值为nil.)

  以下是从数组生成哈希表的方法示例(可能您觉得应该有更直接的方法,但实际上并没有).

   1.

    由[索引, 值, ...] 型的数组变为哈希表

    ary = [1,"a", 2,"b", 3,"c"]
    p Hash[*ary]

    # => {1=>"a", 2=>"b", 3=>"c"}

   2.

    由索引和值配对出现的数组变为哈希表

    alist = [[1,"a"], [2,"b"], [3,"c"]]
    p Hash[*alist.flatten]

    #=> {1=>"a", 2=>"b", 3=>"c"}

   3.

    由索引数组和值数组配对生成哈希表(version 1.7 以后)

    keys = [1, 2, 3]
    vals = ["a", "b", "c"]
    alist = keys.zip(vals) # 或 alist = [keys,vals].transpose
    p Hash[*alist.flatten]

    #=> {1=>"a", 2=>"b", 3=>"c"}

   4.

    虽然索引和值都是数组,但还是无法使用(2)或(3)的方法时,只好老老实实地赋值了

    h = Hash.new
    alist = [[1,["a"]], [2,["b"]], [3,["c"]]]
    alist.each {|k,v|
    h[k] = v
    }
    p h

    #=> {1=>["a"], 2=>["b"], 3=>["c"]}

Hash.new([ifnone])
Hash.new {|hash, key| ...} ((<ruby 1.7 特性>))

  生成一个全新的空哈希表.若索引没有对应值时,其默认值为ifnone.您必须谨慎地处理默认值的问题(trap::Hash).

  ruby 1.7 特性:若指定了块时,则块的计算值将成为默认值.每当调用无值的哈希表元素时,都会对块进行计算,然后返回其结果.而调用哈希表时的索引将被传递给该块.

  # 若没有使用块时, 一旦改变默认值将会
  # 影响到其他的值
  h = Hash.new("foo")
  p h[1]      # => "foo"
  p h[1] << "bar"   # => "foobar"
  p h[1]      # => "foobar"
  p h[2]      # => "foobar"


  # 若使用块的话,问题便会迎刃而解
  h = Hash.new {|hash, key| hash[key] = "foo"}
  p h[1]      # => "foo"
  p h[1] << "bar"   # => "foobar"
  p h[1]      # => "foobar"
  p h[2]      # => "foo"

  # 若元素无值时,可以(像fetch一样)抛出异常
  h = Hash.new {|hash, key|
       raise(IndexError, "hash[#{key}] has no value")
      }
  h[1]
  # => hash[1] has no value (IndexError)

方法:

self[key]

  返回索引为key的哈希表元素的值.若该索引并未注册,则返回默认值(若未设定则为nil).若想区分该nil到底是默认值还是哈希表元素值时,请使用fetch.
self[key]=value
store(key,value)

  将索引为key的元素值设为value.返回value.
clear

  清空哈希表的内容. 返回self.
clone
dup

  返回一个与receiver内容一致的新哈希表. 对冻结的哈希表进行clone时将返回一个同样的冻结的哈希表.但使用dup时,将返回内容相同但却并未冻结的哈希表.
default
default([key]) ((<ruby 1.7 特性>))

  返回哈希表的默认值.

  ruby 1.7 特性: 若哈希表是通过块来取得默认值时(请参考Hash.new),可以使用第二种形式. 此时将以self和key作参数来执行块,并返回其结果. key的缺省值为nil.
default=value

  将哈希表的默认值设为value.若使用无对应值的索引进行搜索时,将返回该值.

  返回value.
default_proc ((<ruby 1.7 特性>))

  返回一个Proc对象,该对象负责返回哈希表的默认值.若没有默认的Proc时将返回nil.

  h = Hash.new {|h, k| }
  p h.default_proc   # => #<Proc:0x0x401a9ff4>

  h = Hash.new(1)
  p h.default_proc   # => nil

delete(key)
delete(key) {|key| ... }

  删除索引key与对应元素之间的关系.返回被删除的值.若没有值与key相对应,则返回nil.

  若给出块的话,将在key匹配失败时对块进行计算,然后返回其结果.
reject {|key, value| ... }

  拷贝self之后对块进行计算,若计算值为真则删除相应的哈希表元素,最后返回该哈希表.

  它与Enumerable#reject基本相同,不同的是它会返回哈希表.
delete_if {|key, value| ... }
reject! {|key, value| ... }

  把key和value当做参数来计算块,若计算值为真则删除相应的元素.

  通常delete_if返回self. reject!就有所不同,若未删除元素时返回nil,除此之外则返回self.
each {|key, value| ... }
each_pair {|key, value| ... }

  以key和value为参数对块进行计算.返回self.

  {:a=>1, :b=>2}.each_pair {|k, v| p [k, v]}

  # => [:a, 1]
   [:b, 2]

  ruby 1.8 特性:

  each和each_pair的块参数交接方法有所不同.

  each:  yield([key, val])
  each_pair: yield(key, val)

  因此,若只向each_pair的块参数传递了一个变量时,将出现下述警告.详情请参考yield.

  {:a=>1, :b=>2}.each_pair {|a| p a }
  # => -:1: warning: multiple values for a block parameter (2 for 1)
    from -:1
   [:a, 1]
   -:1: warning: multiple values for a block parameter (2 for 1)
    from -:1
   [:b, 2]

each_key {|key| ... }

  以key为参数来计算块.返回self.
each_value {|value| ... }

  以value为参数来计算块.返回self.
empty?

  若哈希表为空则返回真.
fetch(key[, default])
fetch(key) {|key| ... }

  返回与索引key对应的元素的值.若该索引未被注册则分为两种情况: 若给出了参数default的话,就返回它的值;若给出了块时,将返回块的计算值.除此之外将引发IndexError异常.(ruby 1.9 特性:将引发IndexError的子类异常KeyError,而不再是IndexError异常.)
has_key?(key)
include?(key)
key?(key)
member?(key)

  若key是哈希表的索引则返回真.
has_value?(value)
value?(value)

  若value是哈希表的元素值则返回真.对值进行判断时使用==操作符.
index(val)

  返回与val对应的索引.若无法对应时返回nil.

  若有若干个对应的索引时,则会随机地返回其中之一.
indexes(key_1, ... , key_n) ((<obsolete>))
indices(key_1, ... , key_n) ((<obsolete>))

  以数组的形式返回与参数所指的索引相对应的元素值.

  ruby 1.8 特性: 该方法在version 1.8中已被禁用.使用时会出现警告信息.此时,应该使用Hash#values_at.
invert

  将元素值和索引互换,返回变换后的哈希表. 请注意:若原哈希表中若干不同的索引对应相同的元素值时,其变换结果将无法预测. 因为该方法原本就不是为这种情况所设计的.

  h = { "n" => 100, "m" => 100, "y" => 300, "d" => 200, "a" => 0 }
  h.invert #=> {200=>"d", 300=>"y", 0=>"a", 100=>"n"}

keys

  返回一个包含所有索引的数组.
length
size

  返回哈希表中的元素的个数.
merge(other)
merge(other) {|key, self_val, other_val| ... }
merge!(other)
merge!(other) {|key, self_val, other_val| ... }

  ruby 1.8 特性

  Hash#merge等同于hash.dup.update.而Hash#merge!则是Hash#update的别名.

  当self和other中包含相同索引时将按照下列两种方式来处理: 若带块则调用该块,然后由用户选择使用哪个值;不带块的话则通常使用other的值.
rehash

  重新计算索引对应的哈希表值。当与索引对应的哈希表值发生变化时,若不使用该方法来重新计算的话,将无法取出与索引对应的哈希表值。
replace(other)

  以other的内容来替换哈希表的内容。返回self。
shift

  删除一个哈希表元素后,再以[key,value]数组的形式将其返回。

  当哈希表为空时,如果没有默认值default则返回nil,如果有默认值的话就返回默认值(请注意,此时并不是以[key,value]的形式返回该值的)。

  h = Hash.new
  p h.empty?     # => true
  p h[0]      # => nil
  p h.shift     # => nil
  p h.default     # => nil
  h.each {|v| p v}   # =>
  p h.to_a      # => []

  h1 = Hash.new("default value")
  p h1.empty?     # => true
  p h1[0]      # => "default value"
  p h1.shift     # => "default value"
  p h1.default    # => "default value"
  h1.each {|v| p v}   # =>
  p h1.to_a     # => []

  # ruby 1.7 特性
  h2 = Hash.new {|arg| arg}
  p h2.empty?     # => true
  p h2[0]      # => [{}, 0]
  p h2.shift     # => [{}, nil]
  p h2.default    # => [{}, nil]
  h2.each {|v| p v}   # =>
  p h2.to_a     # => []

to_a

  生成并返回一个数组,数组中的元素也是数组,且由[key,value]构成。
to_hash

  返回self。
update(other)
update(other) {|key, self_val, other_val| ... } ((<ruby 1.7 特性>))

  合并哈希表的内容。若出现相同索引时,将使用other中对应的元素值。

  ruby 1.7 特性: 若给出了块的话,每当遇到相同索引时都会对块进行计算,然后以块的计算值作为该索引的对应值。此时,索引、self[key] 和other[key]将被作为参数传递给该块。

  foo = {1 => 'a', 2 => 'b', 3 => 'c'}
  bar = {1 => 'A', 2 => 'B', 3 => 'C'}
  p foo.dup.update(bar)       # => {1=>"A", 2=>"B", 3=>"C"}
  p foo.dup.update(bar) {|k,v| v}   # => {1=>"a", 2=>"b", 3=>"c"}

  返回self。
values

  返回一个包括哈希表中的所有元素值的数组。
values_at(key_1, ... , key_n)

  ruby 1.8 特性

  返回一个数组,该数组包括与参数所指索引相对应的哈希表元素值。若没有与索引相对应的哈希表元素值时,将使用default的值。与indexes以及indices相同。

  h = {1=>"a", 2=>"b", 3=>"c"}
  p h.values_at(1,3,4)     # => ["a", "c", nil]
IO类实现了基本的输出输入功能。

  * Traps: 关于打开IO端口的问题

超类:

  * Object

包含的模块:

  * Enumerable
  * File::Constants

ruby 1.8 特性: File::Constants已经脱离了File。
类方法:

IO.new(fd[, mode])
IO.for_fd(fd[, mode]) ((<ruby 1.7 特性>))
IO.open(fd[, mode]) ((<ruby 1.7 特性>))
IO.open(fd[, mode]) {|io| ... } ((<ruby 1.7 特性>))

  生成并返回一个全新的IO对象,它对应于已打开的文件描述符fd。若生成IO对象失败的话,将引发Errno::EXXX异常。

  可以采用与File.open相同的形式来为mode指定一个IO模式(但只能是字符串形式)。详情请参考内部函数open。 mode的默认值为 "r"。

  ruby 1.7 特性: IO.for_fd与IO.new相同。IO.open稍有不同,因为它可以带块(块运行结束时fd会被关闭)。

  带块的IO.open返回块的结果。其他的返回生成的IO对象。

  ruby 1.8 特性: 指定mode的方法与open,File.open完全相同。(也就是说,在1.8以后的版本中,可以使用File::RDONLY等常数(数值)来指定mode)
IO.foreach(path[, rs]) {|line| ... }

  对path所指文件的各行内容进行迭代操作(与open一样,若path以"|"开头的话则读取命令输出)。其运作情形如下。

  port = open(path)
  begin
  port.each_line {|line|
   ...
  }
  ensure
  port.close
  end

  若成功打开path就返回nil。若失败则引发Errno::EXXX异常。

  使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/。

  若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。
IO.pipe

  执行pipe(2)后返回一个数组,该数组包括2个互联的IO对象。若没有成功生成IO对象的话,将引发Errno::EXXX异常。

  返回数组中的首元素负责读取,第二个元素负责读入。

  p pipe = IO.pipe  # => [#<IO:0x401b90f8>, #<IO:0x401b7718>]
  pipe[1].puts "foo"
  p pipe[0].gets  # => "foo\n"

IO.popen(command [, mode])
IO.popen(command [, mode]) {|io| ... }

  将command作为子进程来运行,然后建立一条连接到该进程的输入输出的管线(pipeline)。mode指定打开IO端口的模式(欲知mode详情,请参考open)。省略时将使用默认值 "r"。

  返回生成的管道(IO对象)。

  p io = IO.popen("cat", "r+") # => #<IO:0x401b75c8>
  io.puts "foo"
  p io.gets # => "foo\n"

  若带块时,将以生成的IO对象为参数来运行该块,并返回其结果。在块得到运行以后,生成的管道将会自动关闭。

  p IO.popen("cat", "r+") {|io|
  io.puts "foo"
  io.gets
  }
  # => "foo\n"

  当命令名为"-"时,Ruby将运行fork(2)来建立一个连接到子进程的输入输出的管线。此时,父进程将返回IO对象,子进程返回nil。若带块的话,父进程以生成的IO对象为参数来运行该块并返回其结果。(管道被关闭)子进程以nil为参数来运行该块然后终止运行。

  # 不带块的例子

  io = IO.popen("-", "r+")
  if io.nil?
  # child
  s = gets
  print "child output: " + s
  exit
  end

  # parent
  io.puts "foo"
  p io.gets       # => "child output: foo\n"
  io.close

  # 带块的例子

  p IO.popen("-", "r+") {|io|
  if io
   # parent
   io.puts "foo"
   io.gets
  else
   # child
   s = gets
   puts "child output: " + s
  end
  }
  # => "child output: foo\n"

  若没有成功生成管道或子进程时,将引发Errno::EXXX异常。

  ruby 1.9 特性: 若command为数组则不必通过shell即可运行子进程。
IO.read(path,[length,[offset]]) ((<ruby 1.7 特性>))

  在path所指文件中,从offset位置开始读入length字节的内容并将其返回。其运作情形如下。

  port = open(path)
  port.pos = offset if offset
  begin
  port.read length
  ensure
  port.close
  end

  若length为nil或被省略时,将一直读到EOF。

  若IO已经到达EOF时则返回nil。

  若无法打开path,或者设定offset所指位置失败,又或者无法读入文件内容时,都将引发Errno::EXXX异常。若length为负数,则会引发ArgumentError异常。
IO.readlines(path[, rs])

  读入path所指文件的全部内容后,以行为单位将其转化为数组并返回该数组。若IO已经到达EOF时返回空数组[]。

  其运作情形如下。

  port = open(path)
  begin
  port.readlines
  ensure
  port.close
  end

  使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/。

  若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

  若无法打开path或者读取文件失败时,将引发Errno::EXXX异常。
IO.select(reads[, writes[, excepts[, timeout]]])

  执行select(2)。传递给reads/writes/excepts的是等待输入的IO(或其子类)的实例的数组。

  timeout可以是整数、Float或nil(省略时的默认值)。指定为nil时,将会一直等到IO变成就绪状态。

  timeout时将返回nil,除此以外将返回一个包含3个元素的数组,这3个元素分别是等待输入/输出/异常的对象的数组(指定数组的子集)。

  与select相同。
IO.sysopen(path[, mode [, perm]]) ((<ruby 1.7 特性>))

  打开path所指文件并返回文件描述符。若无法打开文件时将引发Errno::EXXX异常。

  参数mode, perm的具体情况与内部函数open相同。

  如果不使用IO.for_fd等来转化为IO对象的话,就无法关闭使用该方法打开的文件。

方法:

self << object

  输出object。若object并非字符串时,将使用to_s方法将其变为字符串。该方法以self作为返回值,因此可以像下面这样使用一连串的<<。

  STDOUT << 1 << " is a " << Fixnum << "\n"

  若输出失败时将引发Errno::EXXX异常。
binmode

  将流变为二进制模式。该方法只在那些支持二进制模式的OS,如MSDOS中有效(除此以外将毫无反应)。若想从二进制模式恢复到普通模式时,只能重新打开。

  返回self。
clone
dup

  返回一个全新的IO对象,该对象与receiver使用同一个IO。(请参考dup(2)来了解所用的文件描述符)。clone时self暂时被flush。

  对一个被冻结的IO使用clone时,同样会得到一个被冻结的IO。如果使用dup则会返回一个内容相同但未被冻结的IO。
close

  关闭输入输出端口。

  此后,若对该端口进行输入输出的话会引发IOError异常。进行垃圾回收时,未关闭的IO端口将被关闭。Traps:将close托付给GC。

  若close失败则引发Errno::EXXX异常。

  若self已被管道连接到进程上时,将等待该进程的结束。

  返回nil。
close_read

  关闭读取用的IO。主要用在管道或读写两用的IO对象上。

  若self并非读取用IO,则引发IOError异常。

  若close失败则引发Errno::EXXX异常。

  返回nil。
close_write

  关闭写入用的IO。

  若self并非写入用IO,则引发IOError异常。

  若close失败则引发Errno::EXXX异常。

  返回nil。
closed?

  若端口已被关闭则返回真。
each([rs]) {|line| ... }
each_line([rs]) {|line| ... }

  每次从IO端口读入1行来进行相关处理的迭代器。IO端口必须是以读模式打开的(请参考open)。

  使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/。

  若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

  返回self。
each_byte {|ch| ... }

  每次从IO端口读入1字节的内容。IO端口必须是以读模式打开的(请参考open)。

  返回self。
eof
eof?

  若流(stream)到达文件末端时返回真。
fcntl(cmd[, arg])

  将对IO执行系统调用fcntl。请参考fcntl(2)了解详细的功能。

  若arg为整数,则把它原封不动地传递给fcntl(2)。若为true以及false,则分别传递1和0。若为字符串,则会被当作pack过的结构体(structure)来传给fcntl(2)。 若省略arg时,其默认值为0。

  cmd可以使用附加库fcntl.so中Fcntl模块所提供的值。

  返回fcntl(2)的返回值。若未能成功执行fcntl(2)时,将引发Errno::EXXX异常。
fsync ((<ruby 1.7 特性>))

  对写入用的IO执行系统调用fsync(2)。在flush之后(在OS级别上)将内存中尚未保存到硬盘上的数据写入硬盘。

  成功就返回 0。失败则引发Errno::EXXX异常。若self并非写入用IO时,将引发IOError异常。
fileno
to_i

  返回文件描述符的号码。
flush

  刷新IO端口的内部缓冲区。 若self并非写入用IO时,将引发IOError异常。

  返回self。
getc

  从IO端口读入1个字符,并返回该字符对应的Fixnum。到达EOF时返回nil。
gets([rs])

  读入一行,若成功的话就返回读入的字符串。到达文件末尾时返回nil。其动作与IO#each相同,只不过该方法不进行迭代操作而已。

  使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/。

  若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

  IO#gets与gets一样,将读入的字符串赋值给变量$_。
ioctl(cmd[, arg])

  对IO执行系统调用ioctl,并返回其结果。请参考ioctl(2)以了解详细的功能。

  若arg为整数时就将其原封不动地传递给ioctl。若为字符串,则被看作pack过的结构体来传给ioctl。若省略arg或其值为nil以及false时,将传递0。若为true时将传递1。
isatty
tty?

  若输出输入端口已与tty结合时,返回真。
lineno

  返回当前的行号。
lineno=number

  设定行号。
pid

  若是由IO.popen所生成的IO端口时,则返回子进程的进程ID。除此以外返回nil。
pos
tell

  返回文件指针的当前位置。
pos = n

  将文件指针移动到指定位置。与io.seek(pos, IO::SEEK_SET)相同。
print([arg[, ...]])

  依次将参数输出到IO端口。省略参数时将输出$_。该方法处理参数的方式与print相同(详情请参考这个方法)。

  返回nil。
printf(format[, arg[, ...]])

  与C语言的printf一样,按照format将参数变为字符串,然后输出到self。

  它与printf基本相同,只是该方法的第1个参数不能为IO,且不可省略。请参考sprintf格式化来了解处理参数的详情。

  返回nil。
putc(ch)

  输出字符ch到self。该方法处理参数的方式与putc相同(详情请参考这个方法)。

  返回ch。
puts([obj[, ...]])

  输出各个obj到self然后换行。该方法处理参数的方式与puts相同(详情请参考这个方法)。

  返回nil。
read([length])
read([length[, buf]]) ((<ruby 1.7 特性>))

  若给出了length时,就读取length字节的内容,然后返回该字符串。若IO已到达EOF则返回nil。

  若省略length的话,将读入EOF之前的所有内容。若IO已到达EOF则返回""。

  若读取数据失败则引发Errno::EXXX异常。若length为负数则引发ArgumentError异常。

  ruby 1.7 特性:若将某字符串传给第二参数的话,将使用读入的数据来覆盖该字符串对象,并返回读入的数据。若该字符串的长度刚好等于length时,将不会进行内存分配。若该字符串的长度不等于length时,将暂时把字符串的长度拉长(或缩短)到length的长度(随后又将变成实际读入数据的长度)。

  若在调用read方法时使用了第二参数且数据为空的话(read返回nil时),buf将变为空字符串。

  buf = "x" * 20;
  io = File.open("/dev/null")
  p io.read(10,buf)
  p buf
  => nil
   ""

readchar

  与IO#getc一样,读入1个字符后返回与该字符相对应的Fixnum。若到达EOF则引发EOFError异常。
readline([rs])

  与IO#gets一样,读入1行后返回读入的字符串。若到达EOF则引发EOFError异常。

  使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/。

  若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。

  readline与gets一样,将读入的字符串赋值给变量$_。
readlines([rs])

  读入所有数据后,以行为单位将其转化为数组,并返回该数组。若IO已到达EOF则返回空数组[]。

  使用rs所指字符串进行行的切分,rs的默认值取自内部变量$/。

  若将rs指定为nil,则意味着忽略行的切分。若指定为空字符串""的话,将把连续的换行当作行的切分符(段落模式)。
readpartial(maxlen[, outbuf])

  ruby 1.9 特性

  从IO读入最多maxlen的数据,并返回读入的字符串。此时,若没有现成的数据的话,就会进入阻塞状态并一直等待数据的到来。若有现成的数据的话,哪怕只有1字节也不会进入阻塞状态。若将一个字符串传给第二参数outbuf的话,就会用读入的数据来覆盖该字符串,并返回读入的数据。若IO已到达EOF则引会发EOFError异常。

  如果将阻塞所带来的影响减至最小的话,就可以让readpartial对管道、socket以及终端等的流(stream)作出恰当的反应。只有在下述条件均成立时,readpartial才会进入阻塞状态。

   * 被IO对象使用的stdio中的FILE结构体的缓冲区为空
   * 数据尚未到达流
   * 流变为EOF状态

  当上述条件均成立时,readpartial就会进入阻塞状态,直到有数据出现或者到达EOF为止。

  readpartial的结果如下。

   1. 若stdio的缓冲区不为空,则读取并返回缓冲区中的数据。
   2. 若流中有数据,则读取并返回流中的数据。
   3. 若流变成EOF状态,则引发EOFError异常。

  例如,下例就是在管道中使用该方法的情形。

  r, w = IO.pipe    #     stdio buffer  pipe content
  w << "abc"     #     ""     "abc".
  r.readpartial(4096)  #=> "abc"   ""     ""
  r.readpartial(4096)  # 缓冲区和管道中都没有数据,因此进入阻塞状态

  r, w = IO.pipe    #     stdio buffer  pipe content
  w << "abc"     #     ""     "abc"
  w.close      #     ""     "abc" EOF
  r.readpartial(4096)  #=> "abc"   ""     EOF
  r.readpartial(4096)  # 发生EOFError异常

  r, w = IO.pipe    #     stdio buffer  pipe content
  w << "abc\ndef\n"   #     ""     "abc\ndef\n"
  r.gets       #=> "abc\n"  "def\n"   ""
  w << "ghi\n"     #     "def\n"   "ghi\n"
  r.readpartial(4096)  #=> "def\n"  ""     "ghi\n"
  r.readpartial(4096)  #=> "ghi\n"  ""     ""

  而且readpartial不受nonblock标识的影响。也就是说,即使设置了nonblock标识也会进入阻塞状态。

  另外readpartial的运作情形与未设置nonblock标识的sysread非常相似。特别是当stdio的缓冲区为空时,就更是如出一辙了。
reopen(io)
reopen(name[, mode])

  将自身转接到io上。类也将等同于io(请注意)。

  若第一参数为字符串时,将把流转接到name所指的文件上。

  第二参数的默认值为"r"。ruby 1.8 特性: 若省略第二参数时,将原封不动地继承self的模式。

  返回self。
rewind

  将文件指针移动到头部。IO#lineno变为 0 。
seek(offset[, whence])

  将文件指针由whence移动到offset。whence的值是下列之一。

   * IO::SEEK_SET: 从文件头部开始(默认)
   * IO::SEEK_CUR: 从当前文件指针开始
   * IO::SEEK_END: 从文件尾部开始

  省略whence时,其默认值为IO::SEEK_SET。

  若向着offset移动成功就返回0。若失败则引发Errno::EXXX异常。
stat

  生成并返回一个包含文件状态的File::Stat对象。

  若未能成功读取状态则引发Errno::EXXX异常。

  另外请参考File#lstat、File.stat、File.lstat。
sync

  以真和伪来表示当前的输出同步模式。当输出同步模式为真时,每次调用输出函数时都会刷新缓冲区。
sync=newstate

  设定输出同步模式。newstate为真则表示同步模式,伪则表示非同步模式。返回newstate。
sysread(length)
sysread(length[, buf]) ((<ruby 1.7 特性>))

  使用read(2)进行输入,并返回包含输入数据的字符串。到达文件尾部时会引发EOFError异常。因其不使用stdio,所以如果和gets、getc或eof?等混合使用的话会引起意想不到的混乱。

  若不能成功读取数据则引发Errno::EXXX异常。

  ruby 1.7 特性:若将某字符串传给第二参数的话,将使用读入的数据来覆盖该字符串对象,并返回读入的数据。若该字符串的长度刚好等于length时,将不会进行内存分配。若该字符串的长度不等于length时,将暂时把字符串的长度拉长(或缩短)到length的长度(随后又将变成实际读入数据的长度)。

  若在调用sysread方法时使用了第二参数且数据为空的话(sysread引发EOFError异常时),buf将变为空字符串。

  buf = "x" * 20;
  io = File.open("/dev/null")
  p((io.sysread(10,buf) rescue nil))
  p buf
  => nil
   ""

sysseek(offset[, whence]) ((<ruby 1.7 特性>))

  与lseek(2)相同。若将seek与sysread, syswrite混用的话会引起混乱,此时应该使用本方法。

  若对已缓冲的读取IO执行该方法时,会引起IOError异常。若对已缓冲的写入IO执行该方法时,会发出警告。

  File.open("/dev/zero") {|f|
  buf = f.read(3)
  f.sysseek(0)
  }
  # => -:3:in `sysseek': sysseek for buffered IO (IOError)

  File.open("/dev/null", "w") {|f|
  f.print "foo"
  f.sysseek(0)
  }
  # => -:3: warning: sysseek for buffered IO

  参数的使用方法与IO#seek相同。

  若向着offset位置移动成功则返回移动的位置(从文件头部算起)。若移动失败则引发Errno::EXXX异常。
syswrite(string)

  使用write(2)来输出string。若string并非字符串,将使用to_s尝试将其变为字符串。本方法不使用stdio,因此如果与其他输出方法混用的话会引起意想不到的问题。

  返回实际输出的字节数。若输出失败则引发Errno::EXXX异常。
to_io

  返回self。
ungetc(char)

  送回(unreading)char。若送回2字节以上的内容,则无法保证其准确性。

  返回nil。
write(str)

  对IO端口输出str。若str并非字符串,将使用to_s尝试将其变为字符串。

  除IO#syswrite之外的所有输出方法最后都会调用一个名为“write”的方法,因此替换本方法就可以改变输出函数的行为。

  返回实际输出的字节数。若输出失败则引发Errno::EXXX异常。

常数

SEEK_CUR
SEEK_END
SEEK_SET

  请参考IO#seek。
访问文件用的类。通常使用open或File.open来生成。
超类:

  * IO

包含的模块:

  * File::Constants

ruby 1.8 特性: File::Constants已被包含在IO之中。
类方法:

File.atime(filename)
File.ctime(filename)
File.mtime(filename)

  它们分别返回:文件的最终访问时间/文件状态的最终变更时间/最终更新时间(Time对象)。

  若未能成功取得文件时间则引发Errno::EXXX异常。
File.basename(filename[, suffix])

  返回filename中的最后一条斜线后面的部分。若给出了参数suffix且它和filename的尾部一致时,该方法会将其删除并返回结果。

  例:

  p File.basename("ruby/ruby.c")   #=> "ruby.c"
  p File.basename("ruby/ruby.c", ".c") #=> "ruby"
  p File.basename("ruby/ruby.c", ".*") #=> "ruby"
  p File.basename("ruby/ruby.exe", ".*") #=> "ruby"

  另外,请参考File.dirname和File.extname。

  从1.6.8到1.8.0版本间的修改(小结)

  修改之后,File.basename的动作遵循SUSv3的规定。

  p File.basename("foo/bar/")  # => "bar" 以前是""

File.chmod(mode[, filename[, ...]])
File.lchmod(mode[, filename[, ...]]) ((<ruby 1.7 特性>))

  将文件的模式改为mode。它返回修改文件的个数。若修改模式失败则引发Errno::EXXX异常。

  mode与chmod(2)一样,使用数值来指定其内容。

  lchmod只修改符号连接中的连接本身的模式。在未安装lchmod(2)的系统中调用该方法时会引发NotImplementedError异常。
File.chown(owner, group[, filename[, ...]])
File.lchown(owner, group[, filename[, ...]]) ((<ruby 1.7 特性>))

  修改文件的owner和group。只有超级用户才能修改文件的owner和group。它返回修改文件的个数。若修改失败则引发Errno::EXXX异常。

  owner、group与chown(2)一样,使用数值来指定其内容。若只想修改其中之一时,可以将不想修改的一方指定为nil或-1,这样就可以保持原状了。

  lchown只修改符号连接中的连接本身的owner和group。在未安装lchown(2)的系统中调用该方法时会引发NotImplementedError异常。
File.delete(filename ... )
File.unlink(filename ... )

  删除文件。返回删除文件的个数。若删除失败则引发Errno::EXXX异常。

  该方法是用来删除普通文件的。而删除目录时要使用Dir.rmdir。
File.dirname(filename)

  以字符串的形式返回filename中最后一条斜线之前的部分。若文件名中不含斜线,则返回"."(当前目录)。

  例:

  p File.dirname("dir/file.ext")  # => "dir"
  p File.dirname("file.ext")   # => "."

  另外,请参考File.basename, File.extname 。

  ruby 1.8 特性

  修改后,File.dirname的动作遵守SUSv3的规定。

  p File.dirname("foo/bar/")  # => "foo" 以前是、"foo/bar"
  p File.dirname("foo//bar")  # => "foo" 以前是、"foo/"

File.expand_path(path[, default_dir])

  将path展开为绝对路径后返回该路径字符串。若path是相对路径则以default_dir为基准进行扩展。若没有default_dir或其值为nil时将使用当前目录。

  开头的~会被扩展为主目录(使用环境变量HOME),而~USER会被扩展为相应用户的主目录。

  p File.expand_path("..")   #=> "/home/matz/work"
  p File.expand_path("..", "/tmp") #=> "/"
  p File.expand_path("~")    #=> "/home/matz"
  p File.expand_path("~foo")   #=> "/home/foo"

File.extname(filename) ((<ruby 1.7 特性>))

  返回文件名filename中的扩展名部分(跟在最后的"."之后的部分)。目录名中的"."和文件名头上的"."不会被看作扩展名的一部分。若filename中不含扩展名则返回空字符串。

  p File.extname("foo/foo.txt")  # => ".txt"
  p File.extname("foo/foo.tar.gz") # => ".gz"
  p File.extname("foo/bar")   # => ""
  p File.extname("foo/.bar")   # => ""
  p File.extname("foo.txt/bar")  # => ""
  p File.extname(".foo")    # => ""

  请参考File.basename, File.dirname。
File.fnmatch(pattern, path[, flags]) ((<ruby 1.7 特性>))
File.fnmatch?(pattern, path[, flags]) ((<ruby 1.7 特性>))

  对文件名进行模式匹配(fnmatch(3))。若path与pattern相匹配则返回真。

  pattern中可使用的通配符有`*', `?'和`[]'(与Dir.glob不同的是,这里不能使用`{}' 或 `**/')。

  %w(foo foobar bar).each {|f|
  p File.fnmatch("foo*", f)
  }
  # => true
   true
   false

  flags中可以任意使用下列常数(定义在File::Constants模块中)中的若干个来改变模式匹配的运作情况。flags的默认值为0(不指定标识)。

  FNM_NOESCAPE

   将转义字符`\'看作普通字符。

   # 默认情况下,带\的字符都会匹配该字符本身,
   # 加上此标识后,\被当作普通字符处理。
   p File.fnmatch('\a', 'a')        # => true
   p File.fnmatch('\a', '\a', File::FNM_NOESCAPE) # => true

   # 在前者中,*发生了转义,只会匹配"*"字符
   # 本身。
   p File.fnmatch('\*', 'a')        # => false
   p File.fnmatch('\*', '\a', File::FNM_NOESCAPE) # => true

   # 单独的\则不受此标识的影响,一律匹配于\。
   # (请注意,在单引号内的字符串中,\\就是\)
   p File.fnmatch('\\', '\\')        # => true
   p File.fnmatch('\\', '\\', File::FNM_NOESCAPE) # => true

  FNM_PATHNAME

   通配符`*', `?', `[]'将不再匹配`/'。主要作用在shell的模式匹配中。

   p File.fnmatch('*', '/', File::FNM_PATHNAME) # => false
   p File.fnmatch('?', '/', File::FNM_PATHNAME) # => false
   p File.fnmatch('[/]', '/', File::FNM_PATHNAME) # => false

  FNM_CASEFOLD

   进行匹配时,不区分大小写字母。

   p File.fnmatch('A', 'a', File::FNM_CASEFOLD) # => true

  FNM_DOTMATCH

   通配符`*', `?', `[]'将匹配于开头的`.'。

   p File.fnmatch('*', '.', File::FNM_DOTMATCH)    # => true
   p File.fnmatch('?', '.', File::FNM_DOTMATCH)    # => true
   p File.fnmatch('[.]', '.', File::FNM_DOTMATCH)   # => true
   p File.fnmatch('foo/*', 'foo/.', File::FNM_DOTMATCH) # => true

File.ftype(filename)

  返回表示文件类型的字符串。该字符串应为下列之一。与File.lstat(filename).ftype相同(若为符号连接则返回"link")。

  "file"
  "directory"
  "characterSpecial"
  "blockSpecial"
  "fifo"
  "link"
  "socket"

  "unknown"

File.join(item, item, ...)

  将File::SEPARATOR置入其中连成字符串。它与

  [item, item, ...].join(File::SEPARATOR)

  相同。(此后可能提供DOSISH处理功能,但它依赖于系统环境。)
File.link(old, new)

  生成一个指向old且名为new的硬连接(hard link)。old必须是现存的。

  若成功生成硬连接就返回0。若失败则引发Errno::EXXX异常。
File.new(path[, mode [, perm]])
File.open(path[, mode [, perm]])
File.open(path[, mode [, perm]]) {|file| ... }

  打开path所指文件并返回文件对象。若打开文件失败时引发Errno::EXXX异常。

  参数mode, perm的用法与内部函数open相同。

  open()可以带块。若带块调用时,将把文件对象传给块,然后开始块的运行。当块终止运行时,文件将被自动关闭。

  带块调用时的返回值是块的执行结果。
File.readlink(path)

  以字符串形式返回字符连接的连接对象。若读取连接失败则引发Errno::EXXX异常。
File.rename(from, to)

  修改文件名称。若目录不同时,将进行移动。请参考rename(2)。若目标目录中有同名文件则会进行覆盖。

  若成功移动文件就返回0。若失败则引发Errno::EXXX异常。
File.split(pathname)

  将pathname分为dirname和basename,并返回一个包含这两部分的数组。它与

  [File.dirname(pathname), File.basename(pathname)]

  相同。
File.stat(filename)
File.lstat(filename)

  生成并返回一个包含filename信息的File::Stat对象。若获取信息失败则引发Errno::EXXX异常。

  lstat返回符号连接中的连接本身的信息。在未安装lstat(2)的系统中,它与File.stat相同。

  请参考IO#stat,File#lstat 。
File.symlink(old, new)

  生成一个指向old且名为new的符号连接。

  若成功生成符号连接则返回0。若失败则引发Errno::EXXX异常。
File.truncate(path, length)

  将path所指文件裁减为至多length字节的文件。

  若成功更改大小时返回0。若失败则引发Errno::EXXX异常。
File.umask([umask])

  修改umask。返回修改前的umask值。若省略umask则不修改,返回当前的umask值。
File.utime(atime, mtime[, filename[, ...]])

  修改文件的最终访问时间和更新时间。返回修改的文件数。若修改失败则引发Errno::EXXX异常。

  开始的两个参数必须是,表示时间的数值或Time类的实例。
File.blockdev?(path)

  与FileTest.blockdev?相同。
File.chardev?(path)

  与FileTest.chardev?相同。
File.directory?(path)

  与FileTest.directory?相同。
File.executable?(path)

  与FileTest.executable?相同。
File.executable_real?(path)

  与FileTest.executable_real?相同。
File.exist?(path)

  与FileTest.exist?相同。
File.file?(path)

  与FileTest.file?相同。
File.grpowned?(path)

  与FileTest.grpowned?相同。
File.owned?(path)

  与FileTest.owned?相同。
File.pipe?(path)

  与FileTest.pipe?相同。
File.readable?(path)

  与FileTest.readable?相同。
File.readable_real?(path)

  与FileTest.readable_real?相同。
File.setgid?(path)

  与FileTest.setgid?相同。
File.setuid?(path)

  与FileTest.setuid?相同。
File.size(path)

  与FileTest.size相同。
File.size?(path)

  与FileTest.size?相同。
File.socket?(path)

  与FileTest.socket相同。
File.sticky?(path)

  与FileTest.sticky?相同。
File.symlink?(path)

  与FileTest.symlink?相同。
File.writable?(path)

  与FileTest.writable?相同。
File.writable_real?(path)

  与FileTest.writable_real?相同。
File.zero?(path)

  与FileTest.zero?相同。

方法:

atime
ctime
mtime

  它们分别返回:文件的最终访问时间/文件状态的最终变更时间/最终更新时间(Time对象)。

  若未能成功取得文件时间则引发Errno::EXXX异常。
chmod(mode)

  将文件模式修改为mode.若修改成功则返回0.若失败则引发Errno::EXXX异常.

  mode同chmod(2)一样,使用数值来指定其内容.
chown(owner, group)

  修改文件的owner和group.只有超级用户才能修改文件的owner和group.修改成功则返回0,失败则引发Errno::EXXX异常.

  owner,group同chown(2)一样,使用数值来指定其内容.若将其指定为nil或-1的话,就可以保留现在的状态.
flock(operation)

  锁定文件. 锁定成功时返回0. 失败则引发Errno::EXXX异常. 若在LOCK_NB状态下发生阻塞(block)则返回false.下列是可用的operation列表.

   *

    LOCK_SH

    共享锁. 若干个进程可同时共享锁定.

    根据系统的不同,有时要求锁定对象必须是以读取模式("r","r+"等)打开的才行. 在这些系统中,若对不可读文件进行锁定时,可能会引发Errno::EBADF异常.
   *

    LOCK_EX

    排它锁.在某时刻,只有一个进程能控制锁.

    根据系统的不同,有时要求锁定对象必须是以写入模式("w","r+"等)打开的才行. 在这些系统中,若对不可写文件进行锁定时,可能会引发Errno::EBADF异常.
   *

    LOCK_UN

    解锁.

    除了这种显式的解锁以外, 当Ruby解释器结束(进程结束)时,也会自动解锁.
   *

    LOCK_NB

    非阻塞模式.

    同LOCK_SH | LOCK_NB一样,它可以借用or与其他operation一起使用. 若没有指定LOCK_NB的话,若在阻塞条件下调用flock时,该阻塞将会一直持续到解锁时.

    若指定了LOCK_NB的话,若在阻塞时调用flock则返回false.

    所谓"阻塞时"是指发生下述情况
     o 在其他进程已设置排它锁的情况下进行锁定
     o 在其他进程已经锁定的情况下设置排它锁

    的时候.

  上述常数都被定义在模块中.

  例:

  f = File.open("/tmp/foo", "w")

  f.flock(File:OCK_EX)
  puts "locked by process1"

  fork {
  f = File.open("/tmp/foo", "r")
  f.flock(File:OCK_SH)
  puts "locked by process2"
  sleep 5
  puts "unlocked by process2"
  }

  sleep 5

  f.flock(File:OCK_UN)
  puts "unlocked by process1"
  sleep 1 # <- 为确保子进程能够抢先进行锁定而进行的 sleep
  f.flock(File::LOCK_EX)
  puts "re-locked by process1"

  => locked by process1
   unlocked by process1
   locked by process2
   unlocked by process2
   re-locked by process1

path

  以字符串形式返回打开文件时使用的路径.
lstat

  生成并返回一个包含文件状态信息的File::Stat对象.若未能成功取得文件信息则引发Errno::EXXX异常.

  lstat只返回符号连接中的连接本身的信息. 在那些未安装lstat(2)的系统中,它与IO#stat相同.

  另外,请参考IO#stat,File.stat和File.lstat.
truncate(length)

  将文件裁剪成至多length字节大小的文件. 若文件并不是以写入模式打开的话,将引发IOError异常.

  若修改成功则返回0,若失败则引发Errno::EXXX异常.

常数:

ALT_SEPARATOR

  当系统的文件路径分隔符与SEPARATOR不同时,即可使用该常数.在MS-DOS等系统中是"\",而在UNIX 或Cygwin等系统中则是nil.
PATH_SEPARATOR

  PATH环境变量的元素分隔符.在UNIX中是":",而在MS-DOS等系统中是";".
SEPARATOR
Separator

  文件路径的分隔符. 例如,在将路径名传给处理文件的方法时就会用到它. 该分隔符使得脚本内的路径名的格式统一且不受环境的影响.其值为"/".

内部类:

Constants

  包括File类的相关常数的模块. 请参考File::Constants.
Stat

  表示stat结构体(请参考stat(2))的类. 请参考File::Stat.
为处理与正则表达式的匹配过程相关的信息而设置的类. 可以通过下列途径

  * Regexp.last_match
  * Regexp#match, String#match
  * $~

得到该类的实例.
超类:

  * Object

方法:

self[n]

  返回第n个子字符串. 0表示整个匹配部分. 若n为负值,则从尾部算起(末尾的元素是第-1个). 若不存在第n个元素则返回nil.

  /(foo)(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.to_a   # => ["foobar", "foo", "bar", nil]
  p $~[0]   # => "foobar"
  p $~[1]   # => "foo"
  p $~[2]   # => "bar"
  p $~[3]   # => nil   (不匹配)
  p $~[4]   # => nil   (超出范围)
  p $~[-2]   # => "bar"

self[start..end]

  与Array#[start..end]相同。

  /(foo)(bar)/ =~ "foobarbaz"
  p $~[0..2]  # => ["foobar", "foo", "bar"]

self[start, length]

  与Array#[start, length]相同.

  /(foo)(bar)/ =~ "foobarbaz"
  p $~[0, 3]  # => ["foobar", "foo", "bar"]

begin(n)

  返回第n个子字符串的首字符的偏移量(offset). 0表示整个匹配部分. 若n超出范围则引发IndexError异常. 若第n个子字符串没有匹配部分则返回nil.

  /(foo)(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.begin(0) # => 0
  p $~.begin(1) # => 0
  p $~.begin(2) # => 3
  p $~.begin(3) # => nil
  p $~.begin(-1) # => `begin': index -1 out of matches (IndexError)

end(n)

  返回第n个子字符串的尾字符的偏移量(offset). 0表示整个匹配部分. 若n超出范围则引发IndexError异常. 若第n个子字符串没有匹配部分则返回nil.

  /(foo)(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.end(0) # => 6
  p $~.end(1) # => 3
  p $~.end(2) # => 6
  p $~.end(3) # => nil
  p $~.end(-1) # => `end': index -1 out of matches (IndexError)

captures ((<ruby 1.8 特性>))

  返回一个包含$1,$2,...的数组. 与to_a不同的是,它不含$&. 若群组没有匹配部分,则相应的数组元素为nil.

  /(foo)(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.to_a   # => ["foobar", "foo", "bar", nil]
  p $~.captures   # => ["foo", "bar", nil]

length
size

  返回子字符串的数量(与self.to_a.size相同).

  /(foo)(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.size   # => 4

offset(n)

  返回数组[start, end],它包含第n个子字符串的偏移量.它等同于

  [ self.begin(n), self.end(n) ]

  若第n个子字符串并未完成匹配则返回[nil, nil].
post_match

  返回匹配部分之后的字符串(与$'相同).

  /(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.post_match # => "baz"

pre_match

  返回匹配部分之前的字符串(与$`相同).

  /(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.pre_match # => "foo"

select { ... }

  ruby 1.8 特性

  与self.to_a.select { ... } 相同.
string

  返回匹配对象的拷贝.返回的字符串已被冻结(Object#freeze).
to_a

  返回包含$&,$1,$2,... 的数组。

  /(foo)(bar)(BAZ)?/ =~ "foobarbaz"
  p $~.to_a   # => ["foobar", "foo", "bar", nil]

  另外,请参考captures.
to_s

  返回整个匹配部分.

  /bar/ =~ "foobarbaz"
  p $~    # => #<MatchData:0x401b1be4>
  p $~.to_s   # => "bar"

values_at(index1, index2, ...)

  ruby 1.8 特性

  返回一个数组,它包括与正则表达式中第indexN个括号相匹配的子字符串. 与$&一样,第0个表示整个匹配部分.

  m = /(foo)(bar)(baz)/.match("foobarbaz")
  p m.values_at(0,1,2,3,4) # same as m.to_a.values_at(...)
  p m.values_at(-1,-2,-3)

  => ["foobarbaz", "foo", "bar", "baz", nil]
   ["baz", "bar", "foo"]
您可以使用obj.method(:method_name)将方法变为方法对象.而Method正是这些方法对象的类.它封装了方法的实体(而不是方法名)和被调对象(receiver).与Proc不同的是,它不能保持context.

它与Proc的区别在于: 生成Method之前必须有可供提取的方法,而Proc则没有这些限制.由此可见,Proc属于用过即抛型,而Method是反复利用型.另外,内部包含代码的规模也有不同.Proc包含的代码较少,而Method内部的代码较多.

例:

  *

  对现有方法进行Method对象化 (参考Object#method)

  class Foo
   def foo(arg)
    "foo called with arg #{arg}"
   end
  end

  m = Foo.new.method(:foo)

  p m     # => #<Method: Foo#foo>
  p m.call(1)  # => "foo called with arg 1"

  *

  若需要使用无名方法时,最好是使用Proc

  pr = Proc.new {|arg|
   "proc called with arg #{arg}"
  }

  p pr    # => #<Proc:0x401b1fcc>
  p pr.call(1)  # => "proc called with arg 1"

  *

  在下列情况,Method对象是非常有用的

  class Foo
   def foo() "foo" end
   def bar() "bar" end
   def baz() "baz" end
  end

  obj = Foo.new

  # 将索引与方法的关系存入哈希表中
  methods = {1 => obj.method(:foo),
      2 => obj.method(:bar),
      3 => obj.method(:baz)}

  # 使用索引调出相关方法
  p methods[1].call   # => "foo"
  p methods[2].call   # => "bar"
  p methods[3].call   # => "baz"

  *

  但是,若不需要固化被调(Method对象会一直保存着被调)时,可使用Object#send方法.

  class Foo
   def foo() "foo" end
   def bar() "bar" end
   def baz() "baz" end
  end

  # 将索引和方法(名)的关系存入哈希表
  # 请注意,此时并不包括被调的信息
  methods = {1 => :foo,
      2 => :bar,
      3 => :baz}

  # 使用索引调出相关方法
  # 被调可以是任意对象(并不一定是Foo类的实例)
  p Foo.new.send(methods[1])  # => "foo"
  p Foo.new.send(methods[2])  # => "bar"
  p Foo.new.send(methods[3])  # => "baz"

超类:

  * Object

方法:

self[arg, ...]
call(arg ... )
call(arg ... ) { ... }

  启动被封装在方法对象中的方法. 参数和块将被原封不动地传递给方法.

  为了与普通方法调用取得某种形式上的一致,Ruby特地准备了self[]这种调用形式. 但是它和Array#[ ]这样的[ ]方法之间并没有意义上的关联.

  若方法对象已受污染,就以4级安全级别来执行该方法(请参考与安全级别有关的其他详细信息).
arity

  返回方法对象的参数的个数. 若self的参数个数不定,则返回

  -(最底限个数 + 1)

  信息.
inspect

  请参考Object#inspect. 它返回下列形式的字符串.

  #<Method: klass1(klass2)#method>      (形式1)

  在Method#inspect中,Klass1是被调(receiver)的类名.在UnboundMethod#inspect中,它是生成UnboundMethod对象的类/模块名.

  klass2是定义该方法的类/模块名.而method是方法名.

  module Foo
  def foo
   "foo"
  end
  end
  class Bar
  include Foo
  def bar
  end
  end

  p Bar.new.method(:foo)   # => #<Method: Bar(Foo)#foo>
  p Bar.new.method(:bar)   # => #<Method: Bar(Bar)#bar>

  ruby 1.7 特性: 若klass1与klass2相同时,则为下列形式.

  #<Method: klass1#method>        (形式2)

  ruby 1.7 特性:若是特殊方法,

  #<Method: obj.method>         (形式3)
  #<Method: klass1(klass2).method>      (形式4)

  则返回上述形式的字符串.在第2种形式中,klass1是被调,klass2是定义该方法的对象.

  # 对象的特殊方法
  obj = ""
  class <<obj
  def foo
  end
  end
  p obj.method(:foo)  # => #<Method: "".foo>

  # 类方法(类的特殊方法)
  class Foo
  def Foo.foo
  end
  end
  p Foo.method(:foo)  # => #<Method: Foo.foo>

  # 超类的类方法
  class Bar < Foo
  end
  p Bar.method(:foo)  # => #<Method: Bar(Foo).foo>

  # 以下是(第1种形式)的输出
  module Baz
  def baz
  end
  end

  class <<obj
  include Baz
  end
  p obj.method(:baz)  # => #<Method: Object(Baz)#baz>

to_proc

  生成并返回一个调用(call)self的Proc对象.
unbind

  摘除self同被调(receiver)间的关联之后,返回一个UnboundMethod对象.
未绑定receiver的方法对象的类。它由Module#instance_method、Method#unbind等生成,在使用UnboundMethod#bind获取receiver以后就可以生成Method对象。

例: 我们可以用UnboundMethod来重写Method 类的开篇例程

class Foo
 def foo() "foo" end
 def bar() "bar" end
 def baz() "baz" end
end

# 将索引和方法的对应关系存入哈希表
# 请注意,这里并不包含receiver的信息
methods = {1 => Foo.instance_method(:foo),
    2 => Foo.instance_method(:bar),
    3 => Foo.instance_method(:baz)}

# 使用索引来调用相关方法
# receiver为任意对象(但必须是Foo 类的实例)
p methods[1].bind(Foo.new).call  # => "foo"
p methods[2].bind(Foo.new).call  # => "bar"
p methods[3].bind(Foo.new).call  # => "baz"

例: 使用UnboundMethod来重定义方法(通常情况下使用alias、super等)

class Foo
 def foo
  p :foo
 end
 @@orig_foo = instance_method :foo
 def foo
  p :bar
  @@orig_foo.bind(self).call
 end
end

Foo.new.foo

=> :bar
 :foo

超类:

  * Method version 1.6 以前
  * Object (version 1.8 以后)

方法:

self[args, ...]
call(args, ...)
call(args, ...) { ... }

  如果UnboundMethod尚未bind的话,将无法调用。通常会引发TypeError异常。

  class Foo
  def foo
  end
  end
  Foo.instance_method(:foo).call

  # => -:5:in `call': you cannot call unbound method; bind first (TypeError)

  ruby 1.8 特性:该方法被取消。
bind(obj)

  将self绑定到obj上生成并返回一个bound method对象(即Method对象)。只能对下列两种对象进行绑定:调用过unbind方法的对象的类的实例;内部包含(定义某方法的)模块的类的实例。除此以外将引发TypeError异常。

  例:

  # 类的实例方法的UnboundMethod

  class Foo
  def foo
   "foo"
  end
  end

  # 生成UnboundMethod `m'
  p m = Foo.instance_method(:foo) # => #<UnboundMethod: Foo(Foo)#foo>

  # 生成Method对象,它以Foo的实例为receiver
  p m.bind(Foo.new)     # => #<Method: Foo(Foo)#foo>

  # 生成Method对象,它以Foo的Bar子类
  # 的实例为receiver(被禁止)
  # ruby 1.8 特性: 取消了该限制

  class Bar < Foo
  end
  # p m.bind(Bar.new)     # => -18:in `bind': bind argument must be an instance of Foo (TypeError)

  # 定义同名的特殊方法也不行
  class << obj = Foo.new
  def foo
  end
  end
  p m.bind(obj)       # => -:25:in `bind': method `foo' overridden (TypeError)

  # 模块的实例方法的UnboundMethod

  module Foo
  def foo
   "foo"
  end
  end

  # 生成UnboundMethod `m'
  p m = Foo.instance_method(:foo) # => #<UnboundMethod: Foo(Foo)#foo>

  # 生成Method对象,它以内部包含Foo的Bar类
  # 的实例为receiver
  class Bar
  include Foo
  end
  p m.bind(Bar.new)     # => #<Method: Bar(Foo)#foo>

  # Bar的子类也包含Foo,所以没问题
  class Baz <Bar
  end
  p m.bind(Baz.new)     # => #<Method: Baz(Foo)#foo>

  # 定义同名的特殊方法也不行
  class << obj = Baz.new
  def foo
  end
  end
  p m.bind(obj)       # => -:27:in `bind': method `foo' overridden (TypeError)

to_proc

  生成一个调用(call)self的Proc对象。
unbind

  返回self。

  ruby 1.8 特性:该方法已取消。
模块的类。
超类:

  * Object

类方法:

Module.constants

  以数组的形式返回当前可用的常数名。

  class Foo
  FOO = 1
  end

  p Module.constants

  # 输出中并没有 FOO
  => ["RUBY_PLATFORM", "STDIN", ..., "Foo", ... ]

  另外请参考Module#constants、local_variables、global_variables、Object#instance_variables以及Module#class_variables等。
Module.nesting

  以数组的形式返回当前的类/模块的嵌套信息。

  module Foo
  module Bar
   module Baz
    p Module.nesting
   end
  end
  end
  # => [Foo::Bar::Baz, Foo::Bar, Foo]

Module.new
Module.new {|mod| ... } ((<ruby 1.7 特性>))

  生成并返回一个全新的未命名的模块。

  当首次要求未命名模块提供模块名时,它将检索此前被赋值的常数名,并将搜索到的常数名定为模块名。

  p foo = Module.new # => #<Module 0lx40198a54>
  p foo.name    # => ""
  Foo = foo    # 此处若是 p foo 的话,该模块名就会被定为 "Foo"
  Bar = foo
  p foo.name    # => "Bar" (可能是"Foo",但也可能是"Bar")

  ruby 1.7 特性:若带块的话,将把生成的模块传给块的参数,然后在模块的context中执行该块。此时也是返回生成的模块。等同于

  mod = Module.new
  mod.module_eval {|m| ... }
  mod

  在块的执行过程中,将会执行Module#initialize。

方法:

self <=> other

  比较self和other,当self是other的下级类时返回-1,当它们在同一个类/模块中时返回0,当self是other的上级类时返回1。

  若比较非上下级关系的类时,其运作情况不定。

  若other并非类或模块则引发TypeError异常。

  module Foo
  end
  class Bar
  include Foo
  end
  class Baz < Bar
  end
  class Qux
  end
  p Bar <=> Foo  # => -1
  p Baz <=> Bar  # => -1
  p Baz <=> Foo  # => -1
  p Baz <=> Qux  # => 1 (在version 1.7 中是 nil, 1.8 中是 -1)
  p Qux <=> Baz  # => 1 (在version 1.7 中是 nil, 1.8 中是 -1)

  p Baz <=> Object.new # => :in `<=>': <=> requires Class or Module (Object given) (TypeError)
         # (在version 1.8 中是 nil)

self < other
self <= other
self > other
self >= other

  比较操作符。若self是other的下级时,self < other就会成立。

  比较非上下级关系的类时,返回false。

  若other并非类或模块则引发TypeError异常。

  module Foo
  end
  class Bar
  include Foo
  end
  class Baz < Bar
  end
  class Qux
  end
  p Bar < Foo  # => true
  p Baz < Bar  # => true
  p Baz < Foo  # => true
  p Baz < Qux  # => false (在version 1.8 中是 nil)
  p Baz > Qux  # => false (在version 1.8 中是 nil)

  p Foo < Object.new # => in `<': compared with non class/module (TypeError)

self === obj

  该方法主要用在case语句的比较中。若obj与self之间存在Object#kind_of?关系时就为真。也就是说,在case中检查类、模块的所属关系。

  str = String.new
  case str
  when String  # 计算 String === str
  p true   # => true
  end

ancestors

  按照优先顺序依次将类、模块的超类和内含模块存入数组后返回该数组。

  module Foo
  end
  class Bar
  include Foo
  end
  class Baz < Bar
  p ancestors
  p included_modules
  p superclass
  end
  # => [Baz, Bar, Foo, Object, Kernel]
  # => [Foo, Kernel]
  # => Bar

autoload(const_name, 特性)
autoload?(const_name)

  ruby 1.8 特性

  请参考autoload。
class_eval(src[,fname[,lineno]])
class_eval { ... }

  Module#module_eval的别名。
class_variables

  以数组的形式返回类/模块中定义的类变量名。这也包括超类和内含模块中的类变量。

  请参考local_variables,global_variables,Object#instance_variables,Module.constants以及Module#constants。
const_defined?(name)

  若模块中已经定义了名为name的常数的话就返回真。name可以是Symbol或字符串。

  这不包括超类以及内含模块中定义的常数。(但只有Object例外)

  module Kernel
  FOO = 1
  end

  # 在Object中,对内含模块中的常数也会
  # 返回 true
  p Object.const_defined?(:FOO) # => true

  module Bar
  BAR = 1
  end
  class Object
  include Bar
  end
  # 用户定义的模块也是如此
  p Object.const_defined?(:BAR) # => true

  class Baz
  include Bar
  end
  # 若非Object,则只会检查自身的常数
  p Baz.const_defined?(:BAR)  # => false

const_get(name)

  取出模块中定义的名为name的常数的值。若该常数尚未定义则引发NameError异常。name可以是Symbol或字符串。
const_missing(name) ((<ruby 1.8 特性>))

  若调用了未定义的常数时,Ruby就会调用该方法。所调用常数名的Symbol会被传给该方法的参数。

  默认情形下,该方法会引发NameError异常。

  class Foo
  def Foo.const_missing(id)
   warn "undefined constant #{id.inspect}"
  end

  Bar
  end
  Foo::Bar

  # => undefined constant :Bar
   undefined constant :Bar

const_set(name, value)

  在模块中,定义一个名为name且值为value的常数后返回value。若该模块中已经定义了同名常数时,会发出警告。name可以是Symbol或字符串。
constants

  以数组的形式返回该模块(或类)中定义的常数名。也包括超类和内含模块中的常数。

  请参考Module.constants,local_variables,global_variables,Object#instance_variables以及Module#class_variables。

  例: Module.constnats 与 Module#constnats 之间的差别

  # 为简化输出,先取得启动时的常数列表,然后再剔除它
  $clist = Module.constants

  class Foo
  FOO = 1
  end
  class Bar
  BAR = 1

  # Bar 中包括 BAR
  p constants - $clist      # => ["BAR"]
  # 输出中没有 FOO
  p Module.constants - $clist   # => ["BAR", "Bar", "Foo"]
  class Baz
   # Baz不含常数
   p constants - $clist     # => []

   # 在嵌套类中可以调用外侧类定义的常数,因此
   # BAR被包含在Module.constants之中
   # (Baz类也是Bar的常数,因此亦然)
   p Module.constants - $clist   # => ["BAR", "Baz", "Bar", "Foo"]
  end
  end

include?(mod) ((<ruby 1.7 特性>))

  若self内含mod模块则返回真。

  Foo = Module.new
  class Bar
  include Foo
  end
  class Baz < Bar
  end

  p Bar.include? Foo #=> true
  p Baz.include? Foo #=> true

included_modules

  以数组的形式返回内含模块。请参考Module#ancestors中的例子
instance_method(name)

  返回将self的实例方法对象化的UnboundMethod。name可以是Symbol或字符串。

  请参考Object#method。
method_defined?(name)

  若模块中已定义了名为name的实例方法则返回真。name可以是Symbol或字符串。

  请参考Module#public_method_defined?, Module#private_method_defined?, Module#protected_method_defined?。
module_eval(expr, [fname, [lineno=1]])
module_eval {|mod| .... }

  在模块的context中计算字符串expr并返回其结果。若给出了fname、lineno时,将假设该字符串位于fname文件第lineno行并加以编译,此时可显示文件名/行号等栈跟踪信息。

  若带块时,将在模块的context中计算该块并返回结果。self会被传递给块参数mod。

  “在模块的context中计算”是指,运行中的模块将变为self。也就是说,仿佛将其置入模块定义句中来运行。

  但是,局部变量的作用域将被module_eval的外侧所共享。ruby 1.6 特性:在version 1.6.8 以后的版本中,常数和类变量的作用域也都延伸到了外侧。

  注: 在module_eval的块中定义某方法时所受限制与instance_eval相同。详情请查阅其说明。

  请参考Object#instance_eval,Module#class_eval以及Module.new 。
name
to_s

  返回类、模块的名称。若类或模块尚未命名则返回空字符串(请参考Module.new的例子)。

  若类、模块中有嵌套,则会一并显示父类、父模块的名称。

  module A
  module B
  end
  p B.name #=> "A::B"

  class C
  end
  end
  p A.name  #=> "A"
  p A::B.name #=> "A::B"
  p A::C.name #=> "A::C"

instance_methods([inherited_too])
public_instance_methods([inherited_too])
private_instance_methods([inherited_too])
protected_instance_methods([inherited_too])

  以数组的形式返回某模块中定义的 public/private/protected 方法名。

  instance_methods与public_instance_methods相同。ruby 1.7 特性:instance_methods以数组的形式返回public以及protected方法名。

  若inherited_too为真,则会一并搜索超类的方法。其默认值为假。(ruby 1.8 特性:将来会把参数的默认值设为真。但在此之前,如果省略参数就会发出警告,所以最好还是不要省略参数)

  请参考Object#methods、Object#public_methods、Object#private_methods和Object#protected_methods。

  例:

  class Foo
  private; def private_foo() end
  protected; def protected_foo() end
  public;  def public_foo()  end
  end

  # 取得某类的实例方法列表
  puts "例1:"
  p Foo.instance_methods(false)
  p Foo.public_instance_methods(false)
  p Foo.private_instance_methods(false)
  p Foo.protected_instance_methods(false)

  class Bar < Foo
  end

  # 取得某类的实例方法列表。
  # 想一并取得父类中的实例方法,因此设为true
  # Object的实例方法被排除在外。

  puts "例2:"
  p Bar.instance_methods(true)    - Object.instance_methods(true)
  p Bar.public_instance_methods(true)  - Object.public_instance_methods(true)
  p Bar.private_instance_methods(true) - Object.private_instance_methods(true)
  p Bar.protected_instance_methods(true) - Object.protected_instance_methods(true)

  => 例1:
   ["public_foo"]  # version 1.7 以后、["protected_foo", "public_foo"]
   ["public_foo"]
   ["private_foo"]
   ["protected_foo"]
   例2:
   ["protected_foo"] # version 1.7 以后、["protected_foo", "public_foo"]
   ["public_foo"]
   ["private_foo"]
   ["protected_foo"]

private_class_method(name, ... )
public_class_method(name, ... )

  改变name所指的类方法(类的特殊方法)的可用性。

  返回self。
private_method_defined?(name)
protected_method_defined?(name)
public_method_defined?(name)

  ruby 1.7 特性

  当模块中分别定义了private、protected或 public类型的实例方法(该方法名为name)时返回真。name可以是Symbol或字符串。

  请参考Module#method_defined?。

私有(private)方法:

alias_method(new, old)

  定义方法的别名。它与alias之间的区别在于:

   * 方法名可以是Symbol或字符串
   * 不能给全局变量添加别名
   * alias是句法的一部分,不能用在方法中

  返回self。
append_features(module_or_class)

  向模块(或类)添加self的功能。该方法是Module#include的核心,若用Ruby来写include的话可以将其定义如下。

  def include(*modules)
  modules.each {|mod|
   # 因为append_features是私有方法
   # 所以不能直接写成 mod.append_features(self)
   mod.__send__ :append_特性s, self
   # 在1.7 以后的版本中,下列代码也可运行
   # mod.__send__ :included, self
  }
  end

  返回self。
attr(name[, assignable])

  定义一个名为name的读取属性的方法。name可以是Symbol或字符串。通常其返回值为nil。

  以此方法定义的读取属性方法的定义如下。

  def name
  @name
  end

  若使用了第2个可选参数assignable且其值为真时,则意味着同时定义了一个写入属性的 name= 方法。其定义如下。

  def name=(val)
  @name = val
  end

attr_accessor(name, ... )

  为name属性定义读取和写入的方法。name可以是Symbol或字符串。通常其返回值为nil。

  以此方法定义的方法的定义如下。

  def name
  @name
  end
  def name=(val)
  @name = val
  end

attr_reader(name, ... )

  定义name属性的读取方法。name可以是Symbol或字符串。通常返回值为nil。

  以此方法定义的属性读取方法的定义如下。

  def name
  @name
  end

attr_writer(name, ... )

  定义name属性的写入方法(name=)。name可以是Symbol或字符串。通常返回值为nil。

  以此方法定义的写入方法的定义如下。

  def name=(val)
  @name = val
  end

define_method(name, method)
define_method(name) { ... }

  定义名为name的实例方法。method可以是Proc、Method或UnboundMethod这三者之一的实例。当指定了method参数时,就返回该参数。若带块调用时,会将块变成Proc化对象,然后返回该对象。

  例:

  class Foo
  def foo() p :foo end
  define_method(:bar, instance_method(:foo))
  end
  Foo.new.bar  # => :foo

  带块调用时,各版本的处理方式不尽相同。在Ruby 1.7以后的版本中,在执行新定义的方法时,将会在receiver类的实例的基础上对块执行instance_eval。而在Ruby 1.6版本中,只是在块与方法之间取得关联,在执行新定义的方法时,块只是运行在生成时的context中。请参考下例。

  class C
  end
  # 定义实例方法 print_self 。
  # 但因为 define_method 是私有方法
  # 所以不能直接调用。必须借助于 __send__ 来进行调用。
  C.__send__(:define_method, :print_self) { p self }

  # 在 1.6 版本中
  C.new.print_self  #=> main
  # 在 1.7 版本中
  C.new.print_self  #=> #<C:0x4015b490>

extend_object(object)

  Object#extend的核心。向对象追加模块的功能。若用Ruby来写Object#extend的话,可将其定义如下。

  def extend(*modules)
  modules.each {|mod| mod.__send__ :extend_object, self }
  end

  在默认情况下,extend_object是以object的特殊方法的形式来追加self中定义的方法。

  返回object。
extended(class_or_module) ((<ruby 1.8 特性>))

  当其他对象extend到self时就调用该方法。此时会将进行extend操作的对象传递给参数。

  module Foo
  def self.extended(mod)
   p "#{mod} extend #{self}"
  end
  end

  Object.new.extend Foo

  # => "#<Object:0x401cbc3c> extend Foo"

include(module ... )

  对指定模块的性质(方法、常数或类变量)进行添加。返回self。include正是为实现Mix-in(糅合)功能而设计的,而Mix-in取代了多重继承。

  class C
  include FileTest
  include Math
  end

  p C.ancestors

  # => [C, Math, FileTest, Object, Kernel]

  添加模块功能时,先要突破类的继承关系,而后插入模块就可以实现功能的扩展。所以在搜索方法等过程中,首先要搜索添加的模块,然后才搜索超类(上例中的ancestors的结果正显示了搜索方法的顺序)。

  若多次include同一个模块时,则只有首次include是有效的。

  module Foo;       end
  class Bar;   include Foo; end
  class Baz < Bar; include Foo; end # <- 该include无效

  p Baz.ancestors # => [Baz, Bar, Foo, Object, Kernel]

  若include引起模块间的循环继承时,将引发ArgumentError异常。

  module Foo; end
  module Bar; include Foo; end
  module Foo; include Bar; end

  => -:3:in `append_features': cyclic include detected (ArgumentError)
    from -:3:in `include'
    from -:3

  ruby 1.7 特性:若向参数指定了多个模块时,将从最后一个参数起,依次向前进行include。
included(class_or_module) ((<ruby 1.7 特性>))

  当self被某个类或模块include时,解释器会以该类或模块为参数来调用本方法。

  module Foo
  def self.included(mod)
   p "#{mod} include #{self}"
  end
  end
  class Bar
  include Foo
  end
  # => "Bar include Foo"

method_added(name)

  当追加了名为name的方法时,解释器会调用本方法。传给name的是追加方法名的Symbol形式。

  class Foo
  def Foo.method_added(name)
   puts "method \"#{name}\" was added"
  end

  def foo
  end
  define_method :bar, instance_method(:foo)
  end

  => method "foo" was added
   method "bar" was added

  若想增加钩子来监测特殊方法的添加时,请使用Object#singleton_method_added。
method_removed(name) ((<ruby 1.7 特性>))

  若某方法被Module#remove_method删除时,解释器会调用本方法。传给name的是被删除的方法名的Symbol形式。

  class Foo
  def Foo.method_removed(name)
   puts "method \"#{name}\" was removed"
  end

  def foo
  end
  remove_method :foo
  end

  => method "foo" was removed

  若想增加钩子来监视特殊方法的删除时,请使用Object#singleton_method_removed。
method_undefined(name) ((<ruby 1.7 特性>))

  当使用Module#undef_method或undef来撤销某方法的定义时,解释器就会调用本方法。传给name的是被撤销定义的方法名的Symbol形式。

  class Foo
  def Foo.method_undefined(name)
   puts "method \"#{name}\" was undefined"
  end

  def foo
  end
  def bar
  end
  undef_method :foo
  undef bar
  end

  => method "foo" was undefined
   method "bar" was undefined

  若想添加钩子来监视取消特殊方法定义时,请使用Object#singleton_method_undefined。
module_function([name ... ])

  若不带参数则意味着,此后该模块定义中新增的方法都将成为模块函数。模块函数既是私有方法,同时又是模块的特殊方法。例如,Math模块中定义的方法就是模块函数。

  若有参数时,将把参数所指的方法变为模块函数。

  module_function并不是将“模块函数”这一属性赋予某方法,而是同时定义了私有方法和模块的特殊方法。因此,在对模块函数进行alias时

  module Foo
  def foo
   p "foo"
  end
  module_function :foo
  alias :bar :foo
  end
  Foo.foo    # => "foo"
  Foo.bar    # => undefined method `bar' for Foo:Module (NoMethodError)

  这样只能给私有方法foo添加一个别名,却无法为Foo的特殊方法Foo.foo添加别名。若您一定要给它添加别名的话,可以先添加别名然后再将其变为模块函数。

  module Foo
  def foo
   p "foo"
  end
  alias :bar :foo
  module_function :foo, :bar
  end
  Foo.foo    # => "foo"
  Foo.bar    # => "foo"

  返回self。
private([name ... ])

  若无参数时,将把此后该类或模块中新增的方法都设定为private状态,这样一来就只能以函数方式来调用它们了。

  若有参数时,将把参数所指的方法设定为private状态。

  例:

  class Foo
  def foo1() 1 end  # 默认情况下为 public
  private     # 改为 private
  def foo2() 2 end  # foo2 是 private 方法
  end

  foo = Foo.new
  p foo.foo1    # => 1
  p foo.foo2    # => private method `foo2' called for #<Foo:0x401b7628> (NoMethodError)

  返回self。
protected([name ... ])

  若无参数时,将把此后该类或模块中新增的方法都设定为protected状态,这样一来就只能在方法定义所在的类或其子类中调用它们了。

  若有参数时,将把参数所指的方法设定为protected状态。

  返回self。
public([name ... ])

  若无参数时,将把此后该类或模块中新增的方法都设定为public状态,这样一来就可以任意调用它们了。

  若有参数时,将把参数所指的方法设定为public状态。

  例:

  def foo() 1 end
  p foo     # => 1
  # the toplevel default is private
  p self.foo   # => private method `foo' called for #<Object:0x401c83b0> (NoMethodError)

  def bar() 2 end
  public :bar   # visibility changed (all access allowed)
  p bar     # => 2
  p self.bar   # => 2

  返回self。
remove_class_variable(name)

  删除name所指的类变量,并返回该类变量的值。若模块(或类)中没有指定的类变量的话,将引发NameError异常。

  class Foo
  @@foo = 1
  remove_class_variable(@foo) # => 1
  p @@foo # => uninitialized class variable @@foo in Foo (NameError)
  end

  请参考Module#remove_const,Object#remove_instance_variable。
remove_const(name)

  删除name所指的常数,并返回该常数的值。若模块(或类)中没有指定的常数的话,将引发NameError异常。

  class Foo
  FOO = 1
  p remove_const(:FOO)  # => 1
  p FOO  # => uninitialized constant FOO at Foo (NameError)
  end

  目前仍存在一些限制:您无法删除那些设定内部类/模块的常数以及指定autoload(尚未load)的常数。

  class Object
  remove_const :Array
  end
  => -:2:in `remove_const': cannot remove Object::Array (NameError)

  请参考Module#remove_class_variable,Object#remove_instance_variable。
remove_method(name)
remove_method(name[, name2, ...]) ((<ruby 1.8 特性>))

  从模块中删除name所指的实例方法。若指定的方法尚未被定义时,将引发NameError异常。

  class Foo
  def foo() end
  remove_method(:foo)
  end

  ruby 1.8 特性:可以一次指定多个方法。

  返回self。

  另外,请参考undef_method的例子。
undef_method(name)
undef_method(name[, name2, ...]) ((<ruby 1.8 特性>))

  禁止调用名为name的方法。若指定方法尚未被定义时,将引发NameError异常。

  ruby 1.8 特性:可以一次指定多个方法。

  它和undef之间有两点区别:方法名是字符串或Symbol;可以在方法内使用。

  另外,在是否继承超类定义的这个问题上,它和remove_method之间也有差别。请参考下例。

  class A
  def ok() puts 'A' end
  end
  class B < A
  def ok() puts 'B' end
  end

  B.new.ok # => B

  # 使用undef_method时,即使超类中有同名方法
  # 也无法调用
  class B
  undef_method k
  end
  B.new.ok # => NameError

  # 而使用remove_method时,若超类中有同名方法的话
  # 就可以调用
  class B
  remove_method k
  end
  B.new.ok # => A

  返回self。
superclass

  返回类的超类.

私有方法:

inherited(subclass)

  当定义了某个类的子类时, 解释器就会以新生成的子类为参数来调用本方法. 通常是在执行类定义句之前调用本方法.

  class Foo
  def Foo.inherited(subclass)
   puts "class \"#{self}\" was inherited by \"#{subclass}\""
  end
  end
  class Bar < Foo
  puts "executing class body"
  end

  # => class "Foo" was inherited by "Bar"
   executing class body
Numeric是数值的抽象类.在Ruby中,使用coerce方法就可以在不同数值类间进行运算.

负责运算和比较的(+, -, *, /, <=>)等方法被定义在子类中. 有时为了提高效率,可以在子类中重新定义那些类似于Numeric方法的方法.
超类:

  * Object

包含的模块:

  * Comparable

方法:

+ self

  返回self本身.
- self

  反转self的符号后将其返回.

  该方法定义如下: 使用双目操作符"-"来计算0 - self.
abs

  返回self的绝对值.
ceil

  返回一个等于或大于self的最小的整数.

  请参考round, truncate, to_i, floor.
clone
dup

  返回self.

  ruby 1.7 特性: 在version 1.7中,不允许对数值等immutable对象进行clone或dup.

  1.dup # => in `clone': can't clone Fixnum (TypeError)

coerce(number)

  将number变为可直接与自己进行计算的类型,然后将其存入形如[number, self]的数组并返回它. 数值类的算术操作符在接收到一个无法与自己进行计算的类之后,会调用coerce方法对其进行转换,然后再进行计算.
div(other)

  ruby 1.7 特性

  返回self除以other的整数商.

  p 3.div(2) # => 1

divmod(other)

  以数组[q, m]的形式返回self除以other所得的商(q)和余数(m).

  此处的x,y,q和m的关系如下

  x = y * q + m 且 |m| < |y|

  整数 q 和 数字 m 满足上述条件.

  此外, 在divmod中,余数的符号与other相同(或为0).也就是说

   * 当other > 0 时 0 <= m < other
   * 当other < 0 时 other < m <= 0

  该方法由/ 和 %方法共同定义完成.
floor

  返回一个不超过self的最大的整数.

  请参考round, truncate, to_i,ceil.
integer?

  若self为整数则返回真.
modulo(other)

  返回self除以other后的余数m(参考divmod).

  m的符号与other相同(或为0).也就是说

   * 当other > 0 时 0 <= m < other
   * 当other < 0 时 other < m <= 0

  该方法被定义为%方法的方法调用.(也就是说与%相同)
nonzero?

  0则返回nil,非0则返回self.
quo(other)

  ruby 1.8 特性

  除法运算,它会尽量返回一个接近实数商(quotient)的值.

  p 1.quo(3)  # => 0.3333333333333333

  require 'rational'
  p 1.quo(3)  # => Rational(1, 3)

remainder(other)

  返回self除以other后的余数r(请参考divmod).

  但是r的符号与self相同(或为0).即

   * 当self > 0 时 0 <= r < |other|
   * 当self < 0 时 -|other| < r <= 0

  p (13.modulo(4))  #=> 1
  p (13.modulo(-4))  #=> -3
  p ((-13).modulo(4)) #=> 3
  p ((-13).modulo(-4)) #=> -1

  p (13.remainder(4))  #=> 1
  p (13.remainder(-4))  #=> 1
  p ((-13).remainder(4)) #=> -1
  p ((-13).remainder(-4)) #=> -1

  该方法是由%方法所定义的.
round

  返回最接近self的整数.

  请参考truncate, to_i, ceil, floor.
to_int ((<ruby 1.7 特性>))

  与self.to_i 相同.
truncate

  舍弃小数点后面的部分.

  请参考round, to_i, ceil, floor.
zero?

  若为0则返回真.
step(limit) {|n| ... } ((<ruby 1.7 特性>))
step(limit, step) {|n| ... } ((<ruby 1.7 特性>))

  循环执行块的内容,循环起点是self,步长为step,终点是limit. 同时,step也可以是负数(缺省设置为1).另外,limit和step还可以是Float等.

  若将step设为0会引发ArgumentError异常.

  返回self.

  ruby 1.7 特性: 它脱离了Fixnum, Integer.因此,step也可以是Float.

  1.1.step(1.5, 0.1) {|n| p n}
  => 1.1
   1.2
   1.3
   1.4
   1.5

数值相关类中定义的方法

大多数与数值有关的方法都会在子类中得到重新定义. 这一方面是为了提高效率,另一方面是因为在上级抽象类中无法定义具体细节所致. 请参考下表来了解一下到底各个类中有些什么方法.

cary = [Numeric, Integer, Fixnum, Bignum, Float]
mary = cary.collect {|c| c.instance_methods(false)}
methods = mary.flatten.uniq.sort

methods.each_with_index {|op, i|
 if i % 10 == 0
  heading = sprintf("%12s %10s %10s %10s %10s %10s",
      "", *cary.collect {|klass| klass.name.center(10)})
  puts heading
  puts "-" * heading.size
 end

 printf("%12s | %10s %10s %10s %10s %10s\n",
  op, *mary.collect {|ms| (ms.member?(op) ? "o" : "-").center(10)})
}
=> ruby 1.6.8 (2002-12-24) [i586-linux]
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
     % |  -    -    o    o    o
     & |  -    -    o    o    -
     * |  -    -    o    o    o
     ** |  -    -    o    o    o
     + |  -    -    o    o    o
     +@ |  o    -    -    -    -
     - |  -    -    o    o    o
     -@ |  o    -    o    o    o
     / |  -    -    o    o    o
     < |  -    -    o    -    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
     << |  -    -    o    o    -
     <= |  -    -    o    -    o
    <=> |  o    -    o    o    o
     == |  -    -    o    o    o
    === |  o    -    -    o    -
     > |  -    -    o    -    o
     >= |  -    -    o    -    o
     >> |  -    -    o    o    -
     [] |  -    -    o    o    -
     ^ |  -    -    o    o    -
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
    abs |  o    -    o    o    o
    ceil |  o    o    -    -    o
    chr |  -    o    -    -    -
    clone |  o    -    -    -    -
   coerce |  o    -    -    o    o
    div |  -    -    -    o    -
   divmod |  o    -    o    o    o
   downto |  -    o    o    -    -
    eql? |  o    -    -    o    o
   finite? |  -    -    -    -    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
    floor |  o    o    -    -    o
    hash |  -    -    -    o    o
   id2name |  -    -    o    -    -
  infinite? |  -    -    -    -    o
   integer? |  o    o    -    -    -
   modulo |  o    -    o    o    o
    nan? |  -    -    -    -    o
    next |  -    o    o    -    -
   nonzero? |  o    -    -    -    -
  remainder |  o    -    -    o    -
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
    round |  o    o    -    -    o
    size |  -    -    o    o    -
    step |  -    o    o    -    -
    succ |  -    o    o    -    -
    times |  -    o    o    -    -
    to_f |  -    -    o    o    o
    to_i |  -    o    -    -    o
   to_int |  -    o    -    -    -
    to_s |  -    -    o    o    o
   truncate |  o    o    -    -    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
    type |  -    -    o    -    -
    upto |  -    o    o    -    -
    zero? |  o    -    o    o    o
     | |  -    -    o    o    -
     ~ |  -    -    o    o    -
=> ruby 1.8.0 (2003-08-04) [i586-linux]
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
     % |  -    -    o    o    o
     & |  -    -    o    o    -
     * |  -    -    o    o    o
     ** |  -    -    o    o    o
     + |  -    -    o    o    o
     +@ |  o    -    -    -    -
     - |  -    -    o    o    o
     -@ |  o    -    o    o    o
     / |  -    -    o    o    o
     < |  -    -    o    -    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
     << |  -    -    o    o    -
     <= |  -    -    o    -    o
    <=> |  o    -    o    o    o
     == |  -    -    o    o    o
     > |  -    -    o    -    o
     >= |  -    -    o    -    o
     >> |  -    -    o    o    -
     [] |  -    -    o    o    -
     ^ |  -    -    o    o    -
    abs |  o    -    o    o    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
    ceil |  o    o    -    -    o
    chr |  -    o    -    -    -
   coerce |  o    -    -    o    o
    div |  o    -    o    o    -
   divmod |  o    -    o    o    o
   downto |  -    o    -    -    -
    eql? |  o    -    -    o    o
   finite? |  -    -    -    -    o
    floor |  o    o    -    -    o
    hash |  -    -    -    o    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
   id2name |  -    -    o    -    -
  infinite? |  -    -    -    -    o
   integer? |  o    o    -    -    -
   modulo |  o    -    o    o    o
    nan? |  -    -    -    -    o
    next |  -    o    -    -    -
   nonzero? |  o    -    -    -    -
    quo |  o    -    o    o    -
  remainder |  o    -    -    o    -
    round |  o    o    -    -    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
    size |  -    -    o    o    -
    step |  o    -    -    -    -
    succ |  -    o    -    -    -
    times |  -    o    -    -    -
    to_f |  -    -    o    o    o
    to_i |  -    o    -    -    o
   to_int |  o    o    -    -    o
    to_s |  -    -    o    o    o
   to_sym |  -    -    o    -    -
   truncate |  o    o    -    -    o
       Numeric  Integer  Fixnum  Bignum  Float
 ---------------------------------------------------------------------
    upto |  -    o    -    -    -
    zero? |  o    -    o    -    o
     | |  -    -    o    o    -
     ~ |  -    -    o    o    -
整数的抽象类. 其子类包括Fixnum 和 Bignum. 这两类整数可根据长度进行自动变换. 在位操作中,可将整数看成无限长的位串.
超类:

  * Numeric

包含的模块:

  * Precision

类方法:

Integer.induced_from(num)

  将num变为Integer并返回变换结果.

方法:

self[nth]

  若第nth位(最下位(LSB)是第0位)是1就返回1,除此之外返回0.

  之所以Integer中没有self[nth]=bit是因为, Numeric的相关类是immutable.

方法:

self + other
self - other
self * other
self / other
self % other
self ** other

  算术操作符. 分别表示和、差、积、商、余数(模)、幂.
self <=> other

  对self和other进行比较. 若self较大时返回正数, 若相等时返回0, 若较小时返回负数.
self == other
self < other
self <= other
self > other
self >= other

  比较操作符.
~ self
self | other
self & other
self ^ other

  位操作符. 分别表示非、或、与、异或.
self << bits
self >> bits

  移位操作符. 向右(左)移动bits位.

  右移位时,将保留符号位(最上位是(MSB)).

  printf("%#b\n", 0b0101 << 1)
  printf("%#b\n", 0b0101 >> 1)

  => 0b1010
   0b10

  p -1 >> 1

  => -1

chr

  返回与字符代码相对应的1个字节的字符串. 例如65.chr返回 "A".

  相反地,若想得到某字符串的字符代码时,可以使用"A"[0](请参考String#[]).

  整数必需在0到255之间,若超出该范围将引发RangeError异常.
downto(min) {|n| ... }

  循环起点为self,步长为-1,循环终点为min. 若self < min将不作动作.

  请参考upto, step, times.
next
succ

  返回下个整数.
step(limit, step) {|n| ... }

  循环执行块的内容,循环起点是self,步长为step,终点是limit. 同时,step也可以是负数(缺省设置为1).另外,limit和step还可以是Float等.

  若将step设为0会引发ArgumentError异常.

  返回self.

  请参考upto, downto, times.

  ruby 1.7 特性: 请参考Numeric#step.
times {|n| ... }

  循环self(从0到self-1)次. 若self为负则不作动作.

  返回self.

  请参考upto, downto, step.
to_i
to_int

  返回self.
size

  以字节数返回当前条件下的整数的长度.

  当前条件下,Fixnum的sizeof(long)是固定的(在多数32 bit 机器中是 4字节),而Bignum则取决于系统情况.

  p 1.size
  p 0x1_0000_0000.size
  # => 4
   8

to_f

  将数值变为浮点数(Float).
to_s
to_s(base) ((<ruby 1.7 特性>))

  将整数变为10进制字符串形式.

  ruby 1.7 特性: 若使用了参数,则把整数变为以参数为基数的字符串形式. 基数只能是2到36之间的数,若超出范围则引发ArgumentError异常.

  p 10.to_s(2)  # => "1010"
  p 10.to_s(8)  # => "12"
  p 10.to_s(16) # => "a"
  p 35.to_s(36) # => "z"

upto(max) {|n| ... }

  循环起点为self,步长为1,循环终点为max.若self > max则不作动作.

  返回self.

  请参考downto, step, times.