Ruby-元编程之类
最后更新于 2016-12-08 21:07:00
本文的代码均在 Ruby 2.3.0 环境下测试通过。
这篇文章讲述关于 Ruby 中类相关的知识,这也是面向对象语言的核心。事实上,有很多编程语言都具备元编程的能力,而 Ruby 则是将元编程发挥到极致的语言。元编程这个概念是模糊的,很多人都说是用代码生成代码的方式,不过我们不用去纠结这个概念。元编程最具有魅力的地方就是,原来我们还可以在程序运行时去操控代码。
类
我们都知道在面向对象编程中,我们大多数时候都是用类(class)在封装方法和变量,而 Ruby 中的类继承自模块(Module),接下来应该深入到类(模块)中去了解对象模型。
当前类
无论我们的程序运行到哪里,总会存在一个当前对象 self
,而对象是所属类的实例,所以也就存在一个当前类。
result = class A
self
end
p result # ==> A
特别的是,类也是一个对象,它是 Class
类的实例,充当当前对象 self
;但此时的当前类我们更愿意定义为该 self
指向的类,而不是 Class
,因为前者是有意义的。
result.class_eval do
def speak
end
end
p result.instance_methods(false)
# ==> [:speak]
除过使用 class
关键字打开一个类外,我们也可以使用类调用 class_eval()
方法打开一个类,不过后者并没有创建一个独立的作用域,而是块作用域,块中 self
指向类自身;它和 instance_eval()
方法是相似的。
result.class_exec(:speak) do |name|
define_method(name) do
end
end
p result.instance_methods(false)
# ==> [:speak]
class_eval()
方法不允许传递块参数,而 class_exec()
方法会将方法参数传递给块参数。
在类(类方法)定义中,self
指向当前对象,当前对象也是当前类;而在实例方法定义中,self
指向当前对象,当前类则是当前对象的所属类。
类实例变量
类本身也是一个对象,所以我们可以在类中定义类实例变量,这和对象实例变量是一样的,是该类独有的。
class A
@var1 = "class_instance_variable"
def initialize
@var2 = "instance_variable"
end
end
p A.instance_variables
# ==> [:@var1]
p A.new.instance_variables
# ==> [:@var2]
也就是说,实例变量定义时是绑定在self
指向的当前对象身上的,它是该对象独有的变量。