【问题标题】:class methods syntax in rubyruby 中的类方法语法
【发布时间】:2011-11-26 15:16:18
【问题描述】:

我正在阅读的红宝石书让我有些困惑。如果我执行以下操作,我完全理解代码为什么会抛出错误;

class Person
  def show_name
    puts @name
  end
end

person = Person.new
person.show_name
Person.show_name   #(note the capital P) this line falls over

它会抛出一个错误,指出 Person 类没有名为 show_name 的方法,因为它是一个实例方法。我完全理解这一点。本书随后抛出了这个例子;

class Class
  def add_accessor(accessor_name)
    self.class_eval %Q{attr_accessor :#{accessor_name}}
  end
end

class Person
end

person = Person.new
Person.add_accessor :name    #note the capital P
Person.add_accessor :age     #capital P here too

person.name = "Mikey"
person.age = 30

puts person.name

并继续说明您可以动态地将方法添加到类中是多么酷。我不明白的是,当方法本身没有这样定义时,为什么突然允许我将“add_accessor”方法称为类方法(大写P)?我以为所有的类方法都必须这样声明?

class Math
  def self.PI
    3.141
  end
end

puts Math.PI

有没有大神赐教?

【问题讨论】:

    标签: ruby syntax


    【解决方案1】:

    Ruby 类与其他所有对象一样都是对象。您的 Person 类实际上是 Class 类的对象,后者又继承自类 Module。当您将方法作为实例方法添加到类 Class 时,您正在为所有类提供一个新方法。 如果您在 Person 中使用 def 声明它,那么没有对象就无法调用它。要为一个类而不是全部添加类方法,您必须在方法名称前加上 self 或类名:

    class Person
        def instance_method
        end
        def self.class_method
        end
        def Person.other_class_method
        end
    end
    

    当您将方法声明为self.class_method 时,您将您的方法声明为类对象上的单例方法。类或模块声明中的self 指的是类对象,这就是self.Person. 相同的原因。 在处理 Ruby 时,请记住 everything 是一个对象,每样东西都有方法。 Ruby 中也没有任何函数,尽管看起来恰恰相反。方法和对象,总是这样。

    【讨论】:

      【解决方案2】:

      看看这个:

      person.instance_of?(Person) #=> true
      Person.instance_of?(Class)  #=> true
      

      您已经为Class 类的所有实例定义了一个实例方法add_accessor,因此Person 类可以使用该方法,因为它是Class 的一个实例。

      我建议你看看 metaprogramming 和 Ruby 对象模型。

      希望这有帮助

      【讨论】:

        【解决方案3】:

        您正在扩展Class 类,并且您的所有类,例如Person,都是Class 的实例(是的,类是Class 类的实例。它们是普通对象)。

        所以当你调用Person.add_accessor时,你调用的是实例方法Class#add_accessor

        【讨论】:

          【解决方案4】:

          因为 Person(大写 P )是类 Class 的一个实例。

          【讨论】:

            猜你喜欢
            • 2016-02-12
            • 1970-01-01
            • 2011-05-12
            • 2021-09-05
            • 1970-01-01
            • 1970-01-01
            • 2011-12-01
            • 2020-11-15
            • 2012-07-09
            相关资源
            最近更新 更多