一些 Ruby Dynamic Features 記事 (1) OOP

趁過年把 The Ruby Way 拿起來讀一讀,大部頭一本沒辦法從頭念到尾,就挑了最重要的第11章( OOP and Dynamic Features in Ruby) 來念。這個主題值得閱讀的還有 Ruby for Rails 第13章(Ruby dynamics) 跟最近出的 Advanced Rails 一書第1章(Foundational Techniques),因此這幾篇文我還會修修改改就是了。

A “Fancy” Constructor

class Foo
 attr_accessor :a,:b
 def initialize(&block) 
  instance_eval &block
 end
end

於是可以傳入 block 來使用建構式

bar = Foo.new do
 self.a = 1
 self.b = 2
end

class instance variables

因為 Ruby 的 class 也是物件(即 Object 的 instance ),所以除了 class variable 跟 instance variable 之外,還有種變數叫做 class instance variables (即 class Class 的 instance variable 叫做 the class instance variable)。

class Foo
@@var =1 # 這是 class variable
@var = 2 # 這是 class instance variable
attr_accessor :var #這將定義出 instance variable

class << self
 attr_accessor :var2 #這將定義出 class instance variable
end

 def initialize
  @var,@var2 = 4,5 # 這是 instance variable
 end

 def mymethod1
  puts @@var # 1 這是 class variable
  puts @var # 4  這是 instance variable
  puts @var2 # 5  這是 instance variable
 end

 def Foo.classmethod
  puts @@var # 1 這是 class variable
  puts @var # 2 這是 class instance variable
  Foo.var2 = 6 # 這也是 class instance variable
end
end

class BarOne < Foo
  self.var2 = 7
end

class BarTwo < Foo
  self.var2 = 8
end

Foo.classmethod
puts Foo.var2 # 6
puts BarOne.var2 #7
puts BarTwo.var2 #8

class instance variable 跟 class variable 最大的不同在於,class variable 在整個 class 繼承體系都是指同一個,而 class instance variable 則是各個 class 皆不同,因為如此 class instance variable 很多時候比 class variable 好用,像是參數化的 classes。

const_get

const_get 可以從名稱拿到常數:

 str = "PI"
 Math.const_get(str) # 得到 Math::PI

而在 Ruby 裡面所有的 class 也都是 Object 裡的常數,所以要由名稱拿到 class 是這樣寫 :

 classname = "Array"
 klass = Object.const_get(classname) # 拿到 Array
 arr = klass.new(4,1) # [1,1,1,1]

binding

利用 eval 跟內建的 Binding 物件,我們可以把當下的 context 傳到函數裡面,建立出與本來的 scope 一樣的執行環境(因此這裡可以存取到 local variables )。

def print_var( var_name, binding )
 eval "puts #{var_name}", binding
end

foobar = 10
print_var( 'foobar' , binding )

參與討論

2 則留言

  1. 请教一下:在你例子中第三行定义的 这个var变量
    attr_accessor :var #這將定義出 instance variable
    和在
    def initialize
    @var,@var2 = 4,5 # 這是 instance variable
    end
    中定义的@var,是否是同一个变量?

發佈留言

發表迴響