作用域
Ruby中不具備嵌套作用域(即在內(nèi)部作用域,可以看到外部作用域的)的特點(diǎn),它的作用域是截然分開的,一旦進(jìn)入一個(gè)新的作用域,原先的綁定會(huì)被替換為一組新的綁定。
程序會(huì)在三個(gè)地方關(guān)閉前一個(gè)作用域,同時(shí)打開一個(gè)新的作用域,它們是:
上面三個(gè)關(guān)鍵字,每個(gè)關(guān)鍵字對(duì)應(yīng)一個(gè)作用域門(進(jìn)入),相應(yīng)的end則對(duì)應(yīng)離開這道門。
扁平化作用域
從一個(gè)作用域進(jìn)入另一個(gè)作用域的時(shí)候,局部變量會(huì)立即失效,為了讓局部變量持續(xù)有效,可以通過規(guī)避關(guān)鍵字的方式,使用方法調(diào)用來代替作用域門,讓一個(gè)作用域看到另一個(gè)作用域里的變量,從而達(dá)到目的。具體做法是,通過Class.new替代class,Module#define_method代替def,Module.new代替module。這種做法稱為扁平作用域,表示兩個(gè)作用域擠壓到一起。
示例代碼(Wrong)
my_var = “Success”class MyClass puts my_var #這里無法正確打印”Success” def my_method puts my_var #這里無法正確打印”Success” endend
示例代碼(Right)
my_var = “Success”MyClass = Class.new do puts “#{my_var} in the class definition” define_method :my_method do “#{my_var} in the method” endend
在一些語言中,比如java或C#,有內(nèi)部作用域(inner scope)的概念。在內(nèi)部作用域可以看到外部作用域(outer scope)中的變量。但ruby中沒有這種嵌套式作用域的概念,它的作用域是截然分開的,一旦進(jìn)入一個(gè)新的作用域,原先的綁定就會(huì)被替代為一組新的綁定。
在ruby中,程序會(huì)在三個(gè)地方關(guān)閉前一個(gè)作用域,同時(shí)打開一個(gè)新的作用域:類定義、模塊定義、方法。
只要程序進(jìn)入類、模塊或者方法的定義,就會(huì)發(fā)生作用域切換。這三個(gè)邊界分別用class,module和def關(guān)鍵字作為標(biāo)志,每一個(gè)關(guān)鍵字都充當(dāng)了一個(gè)作用域門(scope gate)。
怎樣讓綁定穿越一個(gè)作用域門呢?比如下面的代碼:
my_var = “hello”class MyClass #你希望在這里能打印my_var def my_method #...還有這里 endend
在進(jìn)入另一個(gè)作用域時(shí),局部變量會(huì)立刻失效。如果把class關(guān)鍵字替換為某個(gè)非作用域門的東西,比如方法,就能在一個(gè)閉包中獲得my_var的值,并把這個(gè)閉包傳遞給該方法。代碼如下:
my_var = “hello”MyClass = Class.new do puts “#{my_var} in the class definition” def my_method #...這里怎樣打印出來呢? endend
用Module#define_method()方法可以替代def,代碼如下:
my_var = “hello”MyClass = Class.new do puts “#{my_var} in the class definition” define_method :my_method do puts “#{my_var} in the method” endend MyClass.new.my_method
hello in the class definitionhello in the method
共享作用域
將一組方法定義到,某個(gè)變量的扁平作用域中,可以保證變量僅被有限的幾個(gè)方法所共享。這種方式稱為共享作用域。
新聞熱點(diǎn)
疑難解答
圖片精選