ruby 中的类方法语法

发布于 2024-12-17 21:46:40 字数 852 浏览 1 评论 0原文

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

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

有人能启发我吗?

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. 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? 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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

土豪我们做朋友吧 2024-12-24 21:46:40

Ruby 类与其他所有对象一样都是对象。您的 Person 类实际上是 Class 类的一个对象,而 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 时,只要记住一切都是对象,一切都有方法。 Ruby 中也没有函数,尽管表面上与此相反。方法和对象,始终如此。

Ruby classes are objects like everything else to. Your Person class is really an object of class Class, which in turn inherits from class Module. When you add a method to class Class as an instance method, you are providing a new method for all classes.
If you had declared it with a def in Person, it would not be callable without an object. To add class methods for one class, but not all, you must prepend the method name with self or the name of the class:

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 in a class or module declaration refers to the class object, which is why self. and Person. are the same.
When dealing with Ruby, just remember everything is an object, everything has methods. There are no functions in Ruby either, despite appearances to the contrary. Methods and objects, always.

篱下浅笙歌 2024-12-24 21:46:40

看一下:

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

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

我建议您查看元编程和 Ruby 对象模型。

霍普这有帮助

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.

I recommend yout to take a look at metaprogramming and Ruby Object Model.

Hoep this helps

不醒的梦 2024-12-24 21:46:40

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

因此,当您调用 Person.add_accessor 时,您正在调用实例方法 Class#add_accessor

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).

So when you call Person.add_accessor, you're calling the instance method Class#add_accessor.

酒中人 2024-12-24 21:46:40

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

because Person (with capital P ) is an instance of the class Class.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文