Abstract:
Ruby is a totally OOP language. All things in ruby are objects. We must remember this so that we can understand it well enough.
Here is a useful picture indicates the basic classes of ruby [1]:
当你调用一个方法时,Ruby 向右进入的接收者类,然后向上遍历继承链,直到找到被调用方法或者抵达尽头。在上图中,对象 b 是 Book 类的示例,Book 类包含两个模块:Printable 和 Document。Book 继承自 Object 类,这是 Ruby 中几乎一切事物的基类。Object 包含一个模块Kernel。最后,Object 又继承于 BasicObject 类——Ruby 中一切对象的绝对父类。[1]
Here is another good picture for this[1]:
Our self-defining classes are belongs to Class(Class类的子类). Therefore, we can have an explanation of the Flat Scope Programming.(扁平化编程)
Ruby的 class 也是一个对象,它的类型就是 Class。这似乎有点困惑,但仔细琢磨这句话,意味着我们可以根据类 Class 来实例化一个对象,然后这个对象也是一个类。刚才的例子我们正是这么做的,我们在运行时调用 Class.new 生成了一个类。
Here is a good example of flat scope programming:
my_var = "Success"
MyClass = Class.new do
"#{my_var} in the class definition"
# Have to use dynamic method creation to access my_var
define_method :my_method do
"#{my_var} in the method"
end
end
puts MyClass.new.my_method
# => Success in the method
这么做使得 my_var 变量可以穿越作用域门进入到类定义块中。做这段代码中,你可以有两种方式定义方法。你可以用传统的方式定义类,就像我们定义 foo方法一样--但是这种方式仍然存在作用域门,方法内无法直接引用 my_var 变量。如果你想要 my_var 变量可以穿越作用域门,你需要使用动态定义方法-就像代码中定义 title 方法一样。
Meta-Programming in Ruby:
Here are a good introduction of meta-programming in ruby:
[1] http://www.oschina.net/translate/metaprogramming-in-ruby-part-1
[2] http://www.oschina.net/translate/metaprogramming-in-ruby-part-2
What is meta-programming?
ruby 中的元编程指的是能为你动态地编写代码的代码。是在运行时发生的。元编程就是编写能为你编写代码的代码。
Here I want to emphasise two special means for visiting private instance variable(@variable) in class of ruby.We must notice that the variables in class are automatically defined as private.
① use the attr_accessor (from http://blog.csdn.net/today520/article/details/18412445, this article illustrates the difference of attr_accessor and cattr_accessor. Generally speaking, the former one is used for visiting instance variable while the latter one is used for visiting static variables for class)
Here is the example:
class Test
attr_accessor :name
def initialize()
@name = "yanzilee9292"
end
end
#test
puts Test.new.name
class Counter
cattr_accessor :class_count
attr_accessor :instance_count
end
counter1 = Counter.new
counter1.instance_count = 1
counter1.class_count = 1
counter2 = Counter.new
p counter2.instance_count
#> nil
p counter2.class_count
#> 1
② use the eval (especially instance_eval)
class Test
def initialize()
@name ="yanzilee9292"
end
#test
puts Test.new.instance_eval {@name}
end
Summaries for special symbols in ruby:
1) summary of variables[2][3]:
Ruby 支持五种类型的变量。
一般小写字母、下划线开头:变量(Variable)。
$开头:全局变量(Global variable)。
@开头:实例变量(Instance variable)。
@@开头:类变量(Class variable)类变量被共享在整个继承链中
大写字母开头:常数(Constant)。
以@开始的变量是实例变量,它属于特定的对象。可以在类或子类的方法中引用实例变量。
以@@开始的变量是类变量。在类的定义中定义类变量,可以在定义的时候就赋值,或者在实例方法当中赋值。需要注意一下:
类变量与常数的区别如下。
可以重复赋值(常数则会发出警告)
不能在类的外部直接引用(在继承类中则可以引用/赋值)
类变量与类的实例变量的区别如下。
可在子类中引用/赋值
可在实例方法中引用/赋值
可以把类变量看作一种被类、子类以及它们的实例所共享的全局变量。
模块中定义的类变量(模块变量)被所有包含该模块的类所共享。
以$开始的变量是全局变量,可以在程序的任何地方加以引用(因此需要特别留意)。全局变量无需变量声明。引用尚未初始化的全局变量时,其值为 nil。
2) What does # means?
注意:在 Ruby 中,您可以通过在变量或常量前面放置 # 字符,来访问任何变量或常量的值. 而且#加在类名后,函数成员前,也有时候表示读取类成员。
3) symbol object: http://blog.csdn.net/besfanfei/article/details/7966850
class Test
attr_accessor :test
end
这个类定义了一个具有读写方法的实例变量 @test 。实际上 Ruby 创建了两个 Symbol ,一个是实例变量的symbol :@test ,另一个是 :test 。那如果使用字符串对象 ”test” 作为参数呢?也可以,仍然会创建两个 symbol,:test 和 :@test ,为什么还会创建 :test 呢?这是和Ruby的实现相关的(至少Ruby1.8.6里是这样)。
4) Here is a website for comparing different self:
http://www.bitscn.com/ruby/540989.html
Self is a special variable which is called 当前方法接收器的对象
强调一下关于作用域的问题:
from: http://www.cnblogs.com/smallbottle/p/3871434.html
作用域(scope)指的是变量的可达性或可见性。不同类型的变量有不同的作用域规则。与self类似,作用域在程序的执行过程中也在不断的变化,也可以根据上下文推断出"谁在什么作用域中"。但是,self和作用域不是同一个东西,在self没有变化的时候,可以开始一个新的局部作用域,有时候,作用域和self一起改变。
全局作用域和全局变量:全局变量最不常用,但需要了解。全局变量用$开始,在整个程序的任何位置都可以访问,穿过所有的边界。
局部作用域:在任意时刻,程序都处在一个特定的局部作用域中。两个作用域的主要区别就是可访问的局部变量不同。
ruby中辨别作用域的开始和结束:
顶层有它自己的局部作用域
每一个类或模块定义块(class,module)有它自己的局部作用域,即使是嵌套的类/模块定义块也一样。
每一个方法定义(def)有它自己的局部作用域
每次使用关键字def,class,module引入一个定义块的时候,就开始了一个新的局部作用域。不论它们如何嵌套,都是这样的。这和c语言不一样,c语言中内部作用域可以看到外部作用域的变量,但是ruby中不能。
Reference:
[1] http://www.oschina.net/translate/metaprogramming-in-ruby-part-1