2009-06-10 43 views
2

我在试着理解这个函数。self.class_eval << DEF ... DEF

我可以看到的是一个属性和类型传递给opal()方法。

然后type_name只要typeSymbolString需要从type其值。否则,在type上调用name方法。我想象name方法类似于class方法来获得type参数的类。

self.class_eval我有点失落,但我的猜测是这是定义可能是一个代码块被添加到self引用的类。

这是如何工作我不确定。

如果有人能解释self.class_eval << DEF后发生了什么,我们将不胜感激。

def opal(attr, type) 
     self.ds "#{attr}_id" 
     type_name = (type.is_a?(Symbol) || type.is_a?(String)) ? type : type.name 
     self.class_eval <<DEF 
    def #{attr} 
    if defined?(@#{attr}) 
     @#{attr} 
    else 
     @#{attr} = if self.#{attr}_id 
      #{type_name}.get(self.#{attr}_id) 
     else 
      nil 
     end 
    end 
    end 

    def #{attr}=(value) 
    self.#{attr}_id = value.key 
    @#{attr} = value 
    end 
DEF 
    end 
+2

为什么这次被投票?它与编程有关,这个问题似乎并不清楚。 – 2009-06-10 05:00:55

回答

5

<<DEFDEF之间的一切都只是一个字符串和#{ ... } S于该字符串像任何其他的工作。

class_eval将导致解释器在模块上下文中的字符串上运行。

因此,如果您知道attrtype那么您可以计算出正在运行哪些代码以将方法添加到类中。

可以说attr"foo"type"Bazzle"。该代码正在运行将是:

def foo 
    if defined?(@foo) 
    @foo 
    else 
    @foo = if self.foo_id 
     Bazzle.get(self.foo_id) 
    else 
     nil 
    end 
    end 
end 

def foo=(value) 
    self.foo_id = value.key 
    @foo = value 
end 
+0

你说“class_eval将导致解释器在模块上下文中的字符串上运行”。所以如果我说self.class_eval“def bar end”,解释器会为这个类添加一个“bar”方法? – franz 2009-06-10 05:20:04

3

为了便于理解,让我们假设“ATTR”的值是“富”,这里是它看起来像现在:

self.class_eval <<DEF 
    def foo 
    if defined?(@foo) # Return the value of attr if it's defined 
     @foo 
    else 
     @foo = if self.foo_id 
      #{type_name}.get(self.foo_id) 
     else 
      nil 
     end 
    end 
    end 

    def foo=(value) # Define setter 
    self.foo_id = value.key 
    @foo = value 
    end 
DEF 

所以这只需为@foo定义一些getter和setter方法,并在类级别对其进行评估。