Self Summary: Ruby flat scope programming and meta-programming

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]: 


Self Summary: Ruby flat scope programming and meta-programming_第1张图片


当你调用一个方法时,Ruby 向右进入的接收者类,然后向上遍历继承链,直到找到被调用方法或者抵达尽头。在上图中,对象 b 是 Book 类的示例,Book 类包含两个模块:Printable 和 Document。Book 继承自 Object 类,这是 Ruby 中几乎一切事物的基类。Object 包含一个模块Kernel。最后,Object 又继承于 BasicObject 类——Ruby 中一切对象的绝对父类。[1]


Here is another good picture for this[1]: 


Self Summary: Ruby flat scope programming and meta-programming_第2张图片


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  

and 


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 uses the string object "test" to create a new symbol object :test and :@test. Actually, :test == :"test".  


这个类定义了一个具有读写方法的实例变量 @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


你可能感兴趣的:(Ruby,ruby,meta,programming,元编程,扁平化编程)