0

我正在阅读Paolo Perrotta的Metaprogramming Ruby,我必须说这本书有一个错误,以下是本书第 70 页的 ruby​​ 代码,我将在这里再次过去代码

class Computer
  def initialize(computer_id, data_source)
    @id = computer_id
    @data_source = data_source
  end
  def self.define_component(name)
    define_method(name) {
      info = @data_source.send "get_#{name}_info" , @id
      price = @data_source.send "get_#{name}_price" , @id
      result = "#{name.to_s.capitalize}: #{info} ($#{price})"
      return "* #{result}" if price >= 100
      result
    }
  end
  define_component :mouse
  define_component :cpu
  define_component :keyboard

Computer.define_component是类方法,类似于 Java 中的静态方法。Java 告诉我们的是,静态方法永远无法访问实例属性或没有对象的实例方法。所以,define_component方法不能使用invoke define_method,它是一个实例方法。从逻辑上讲,在创建对象之前调用了类方法,因此无法初始化@data_source并且@id可以初始化(它已经创建了bean)。但是这里没有实例define_component调用。define_method那是对的吗?

4

3 回答 3

4

你错过了一点。确实将define_method无法访问实例变量,但define_method在类上调用时实际上会创建一个常规实例方法。此方法的名称是 define_method 的参数,而这个新实例方法的主体是传递的块。

所以定义方法实际上不会执行代码(它不能)。它将简单地创建一个可以调用来执行代码的新方法。

我希望我明白了这一点。

于 2013-08-29T11:44:27.427 回答
3

好吧,你的想法被java破坏了。这是一种严格的语言,有着严格的规则。Ruby 更强大/更灵活。

def self.define_component(name)
  # class scope here
  define_method(name) {
    # instance scope here. You can use instance-level instance variables.
  }
end

define_component方法在类上定义了一个实例方法。在该实例方法的主体中,您自然可以使用实例变量。

于 2013-08-29T09:01:15.673 回答
1

Ruby 没有静态方法。Ruby 类方法和 Java 静态方法之间唯一的相似之处在于它们都可以在类上调用。

在 Ruby 中,类是对象——它们是名为 Class 的类的实例,它们可以像其他对象一样拥有自己的实例变量。类方法不像 Java 中的静态方法——它是类的单例方法。您可以以完全相同的方式在任何对象上定义特定于实例的方法。

于 2013-08-29T09:14:01.530 回答