![](/img/trans.png)
[英]Ruby singleton methods with (class_eval, define_method) vs (instance_eval, define_method)
[英]Ruby - Using class_eval to define methods
我正在做SaaS Stanford課程,試圖完成這項任務的第5部分
我很難掌握這個概念,這就是我試圖做的事情:
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s
attr_reader attr_name
attr_reader attr_name + '_history'
class_eval %Q'{def #{attr_name}(a);#{attr_name}_history.push(a) ; end;}'
end
end
我可能會做各種各樣的錯誤,閱讀關於元編程的The Book of Ruby章節,我仍然沒有得到它,有人能幫我理解這個嗎?
這很有趣!!!
class Class
def attr_accessor_with_history(attr_name)
attr_name = attr_name.to_s # make sure it's a string
attr_reader attr_name
attr_reader attr_name+"_history"
class_eval %Q"
def #{attr_name}=(value)
if !defined? @#{attr_name}_history
@#{attr_name}_history = [@#{attr_name}]
end
@#{attr_name} = value
@#{attr_name}_history << value
end
"
end
end
class Foo
attr_accessor_with_history :bar
end
class Foo2
attr_accessor_with_history :bar
def initialize()
@bar = 'init'
end
end
f = Foo.new
f.bar = 1
f.bar = nil
f.bar = '2'
f.bar = [1,nil,'2',:three]
f.bar = :three
puts "First bar:", f.bar.inspect, f.bar_history.inspect
puts "Correct?", f.bar_history == [f.class.new.bar, 1, nil, '2', [1,nil,'2',:three], :three] ? "yes" : "no"
old_bar_history = f.bar_history.inspect
f2 = Foo2.new
f2.bar = 'baz'
f2.bar = f2
puts "\nSecond bar:", f2.bar.inspect, f2.bar_history.inspect
puts "Correct?", f2.bar_history == [f2.class.new.bar, 'baz', f2] ? "yes" : "no"
puts "\nIs the old f.bar intact?", f.bar_history.inspect == old_bar_history ? "yes" : "no"
請注意,您需要使用字符串與class_eval的唯一原因是,你可以參考的價值 attr_name
定義自定義設置方法時。 否則,通常會將塊傳遞給class_eval
。
關於你所做的事情,你實際上是在解決方案的尖端。 只是#{attr_name}_history
在您的代碼中不存在。 您將需要創建一個實例變量,如果它不存在則將其設置為nil。 你已經應該處理的數據如果確實存在則推入數組。
有幾種方法可以做到這一點。 一種方法是if defined? @#{attr_name}_history DoStuffHere
if defined? @#{attr_name}_history DoStuffHere
你必須注意#{attr_name}_history
是一個實例變量,所以在下面的類中使用@之前的@foo
def #{attr_name}=value
, #{attr_name}=
是方法名稱, value
是參數,與def func parameter
相同
def #{attr_name}=value
(!defined? @#{attr_name}_history) ? @#{attr_name}_history = [nil, value] : @#{attr_name}_history << value
end
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.