简体   繁体   English

ruby中的类方法语法

[英]class methods syntax in ruby

the ruby book I'm reading has confused me a bit. 我读的红宝石书让我有点困惑。 If I do the following, I understand completely why the code throws an error; 如果我执行以下操作,我完全理解为什么代码会抛出错误;

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

It throws an error stating that the Person class does not have a method called show_name, because it is an instance method. 它抛出一个错误,指出Person类没有名为show_name的方法,因为它是一个实例方法。 I understand this completely. 我完全理解这一点。 The book then throws in this example; 然后这本书抛出了这个例子;

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

and goes on to state how cool it is that you can add methods to classes dynamically. 并继续说明你可以动态地向类添加方法是多么酷。 What I don't understand is why I am suddenly allowed to call the "add_accessor" method as a class method (with a capital P) when the method itself isn't defined as such? 我不明白为什么当方法本身没有这样定义时,我突然被允许将“add_accessor”方法称为类方法(带有大写字母P)? I thought all class methods had to be declared like this? 我以为所有的类方法都必须这样声明?

class Math
  def self.PI
    3.141
  end
end

puts Math.PI

Is anyone able to enlighten me? 有人能够开导我吗?

Ruby classes are objects like everything else to. Ruby类是其他所有对象。 Your Person class is really an object of class Class, which in turn inherits from class Module. 您的Person类实际上是Class类的对象,而Class又继承自Module类。 When you add a method to class Class as an instance method, you are providing a new method for all classes. 将类作为实例方法添加到类Class时,您将为所有类提供新方法。 If you had declared it with a def in Person, it would not be callable without an object. 如果你使用def in Person声明了它,那么没有对象就无法调用它。 To add class methods for one class, but not all, you must prepend the method name with self or the name of the class: 要为一个类(但不是全部)添加类方法,必须在方法名称前加上self或类的名称:

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

When you declare the method as self.class_method you are declaring your method to be a singleton method on the class object. 当您将方法声明为self.class_method您声明您的方法是类对象上的单例方法。 self in a class or module declaration refers to the class object, which is why self. self在类或模块声明中引用类对象,这就是self.原因self. and Person. Person. are the same. 是相同的。 When dealing with Ruby, just remember everything is an object, everything has methods. 在处理Ruby时,只记得一切都是对象,一切都有方法。 There are no functions in Ruby either, despite appearances to the contrary. 尽管出现了相反的情况,但Ruby中也没有任何功能。 Methods and objects, always. 方法和对象,总是如此。

You're extending the Class class, and all of your classes, like Person , are instances of Class (Yes, classes are instances of the Class class. They're ordinary objects). 您正在扩展Class类,并且所有类(如Person )都是Class实例(是的,类是Class类的实例。它们是普通对象)。

So when you call Person.add_accessor , you're calling the instance method Class#add_accessor . 因此,当您调用Person.add_accessor ,您正在调用实例方法Class#add_accessor

Look at this: 看这个:

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

You have defined an instance method add_accessor for all the instances of the class Class , so Person class can use that method because it is an instance of Class . 您已为类Class所有实例定义了实例方法add_accessor ,因此Person类可以使用该方法,因为它是Class的实例。

I recommend yout to take a look at metaprogramming and Ruby Object Model. 我建议你看一下元编程和Ruby对象模型。

Hoep this helps 这有帮助

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM