重定义同一个类时,意味着对原有定义进行补充,不会覆盖原来的定义。而重定义方法时,则会覆盖原有定义。
6.2 有类变量吗?从1.6版本开始出现类变量。类变量名前都带有`@@'。
class Foo @@F = 0 def foo @@F += 1 print @@F, "\n" end end在1.4以前的版本中,使用容器类(Array、Hash等)来代替类变量。
class Foo F = [0] def foo F[0] += 1 print F[0], "\n" end end 6.3 什么是类的实例变量?class Foo @a = 123 # (1) def foo p @a # (2) ... 123でなくnilになる。 end end(1)是类的实例变量、(2)是通常的实例变量。(2)属于Foo类的实例,而(1)属于类对象Foo(Class的实例)。
不能在实例方法中直接访问类的实例变量。
因此上面的实例变量尚未初始化,其值为nil。
6.4 什么是特殊方法?特殊方法是指某实例所特有的方法。
通常这么使用。
foo = Foo.new def foo.hello print "Hello\n" end foo.hello若想向类中添加方法,却又不想生成子类时,可以使用特殊方法。
Java程序员可能会觉得它很像inner class。
6.5 什么是类方法?类方法就是指类的特殊方法。上面我们提到,特殊方法是归属于某对象的方法,那么这里所说的“类的特殊方法”将作何解释呢?其实Ruby中有一个“元类”的概念。它是Class类的实例,同时又被所有的类所共有。类方法就定义在这个元类中。
从形式上看,将类名当作被调的方法就是类方法。
下面,我们就在Class类的Foo实例中添加一个特殊方法。
class Foo def Foo.test print "this is foo\n" end end像这样来调用它。
Foo.test您有没有注意到什么?
对了,这就是所谓的类方法。
当然了,Class中所定义的方法也可以用作类方法。
6.6 什么是特殊类?上面我们提到了特殊方法。
简单说来,在Ruby中可以向对象(实例)中添加方法。
进一步讲,如果您想像操作类那样来操作对象时,该怎么办呢?
可千万别说您没这么想过(^^;
使用特殊类的话,您就可以做到这一点。
class Foo def hello print "hello.\n" end end foo = Foo.new foo.hello #=> hello. class << foo attr :name, true def hello print "hello. I'm ", @name, ".\n" end end foo.name = "Tom" foo.hello #=> hello. I'm Tom.多棒呀。
好了,现在要问问题了
问题 如果不使用private_class_method的话,能不能将类方法变成private呢?
解答: 类方法就是类的特殊方法。
所以我们可以耍个小花招,这么处理它。
class Foo # ... end class << Foo def class_method print "class method\n" end private :class_method end Foo.class_method #=> Error定义特殊方法时,既可以像上面这样在特殊类中加以定义,也可以直接使用def obj.method来完成定义。
另外,您还可以在模块中定义特殊方法(而且是private方法)。
6.7 什么是模块函数?定义模块函数时,它们既是模块的特殊方法,同时又是private类型。例如,您既可以这样
Math.sqrt(2)来调用它,又可以这样
include Math sqrt(2)使用include来调用它,的确十分方便。
若您想把某方法定义成模块函数时,可以在模块定义中添加如下代码
module_function :method_name即可完成定义。
6.8 类和模块有什么区别?模块不能生成实例,而类不能被include。
6.9 模块可以生成子类吗?在类(模块)中include模块之后,就可实现类似于多重继承的Mix-in功能。它与父类子类之间的这种直接继承关系有所不同,内含模块的类与该模块之间存在is_a?的关系。
6.10 在类定义中定义类方法 和 在顶层中定义类方法 之间有什么不同?您在前者中可以直接使用常数,而在后者中则必须指定类名才行。
6.11 load和require有什么不同?load只能加载用Ruby编写的源文件(*.rb)。
require还可以加载*.o文件。另外,一旦require某文件之后,即使再次require也不会进行加载。
加载路径也有所不同。
6.12 include和extend有什么不同?include负责将module插入到类(模块)中,这样就能以函数的形式来调用方法;而extend负责将module插入到对象(实例)中,这样就添加了特殊方法。
6.13 self是什么?self是指执行方法的主体本身。在函数形式的方法中,是把self当作被调的。
6.14 MatchData中的begin、end分别返回什么?它们作用于$~,分别返回$0、$1等原来字符串的开始位置和终止位置。请参考展开标签中的例子。
6.15 如何使用类名来获得类?如果我有classname = "SomeClass"时,如何生成SomeClass类的实例呢?主要有两个解决方法。
eval(classname).new Object.const_get(classname).new第1种方法既简单又可以处理嵌套类(Net::HTTP等),但如果在CGI环境中滥用它的话,将十分危险。
而第2种方法却又无法处理嵌套类的问题。但如果进行以下处理的话,就可以处理嵌套类了。
# 如果只考虑Ruby 1.8之后的版本的话,可以这样 c = classname.split(/::/).inject(Object) {|c,name|