模块的类。
超类:
* 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。