Class 是继承 Object,而 Object 是继承 BasicObject。
可以为特定的对象定义专属于这个对象的方法,名为单例方法。如:
str = 'singleton method' class << str def hello puts "I'm a singleton method" end end str.hello >> I'm a singleton method
由于类 Class 继承于 Object ,所以 Class 本身也是对象。这样,我们可以把为类添加类方法,当作为对象 Class 添加单例方法。
class C class << C def singleton_method puts "I'm one of Class C's methods" end end end C.singleton_method >>I'm one of Class C's methods
由于在类定义中,self 为类本身,因此,如果在类中定义类方法,可以用 self 替代类名,因此衍生出第二种定义类的方法:
class C class << self def singleton_method puts 'I am one of Class methods' end end end
Martz 在设计 Ruby 的时候,把所有程序员设想为合格的程序员,因此,他要程序员为自己所写的代码负责,而不是通过提供受限的编程语言,保证程序员所写的代码质量。所以,由于上面的那种写法不太符合程序员的习惯,因此提供了以下简便一点的方法:
class C def C.class_method puts 'another way to define class methods' end end
同样,使用self
来替换类名得到第四种声明类方法的方法:
class C def self.class_method puts 'use self to replace class name' end end
到此为止,其实类声明的方法就可以结束了。但是本则孔乙己(90s、00s 等没学过这篇文章的需要脑补一下了)的精神胜利法,我再提供另外两种。 因为以上声明类方法的方式中,有两种是可以放在类外部声明的,所以又有了另外两种声明类的方法(lol):
class C end class << C def singleton_method puts 'the fifth way to define class methods' end end def C.singletom_method puts 'the sixth way to define class methods' end
综合以上,终于拼凑够了“回”字的六种写法。
除了定义类方法,我们可以用以下方法,把任何类变成单例类:
# Object本身也是类,(类又继承Object,能不这么虐人吗?)所以打开类Object,为Object添加单例方法: class Object class << self self end end
大神 why the lucky stiff 依据这个,为元编程创建了 Metaid 库:
class Object #将类变为单例类 def metaclass; class << self; self; end; end #看上去是实例方法,其实是类方法 def meta_eval &blk; metaclass.instance_eval &blk; end # 定义类方法 def meta_def name, &blk mate_eval { define_method name, &blk } end #定义类的实例方法 def class_def name, &blk class_eval { define_method name, &blk } end end
引用上述库,定义类方法:
class C end C.meta_def class_method_name { #方法 }
如此说来,共有 7 种定义类的方法了。