Ruby 中的类和该类的单例之间有什么区别? [英] What's the difference between a class and the singleton of that class in Ruby?

查看:47
本文介绍了Ruby 中的类和该类的单例之间有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,所以我正在尝试用 Ruby 进行一些元编程,但我有点困惑.根据我读过的几篇文章(比如这个),为了给Ruby类动态添加类方法,必须使用类的单例类:

Okay, so I'm trying to do some metaprogramming in Ruby and I'm getting a bit confused. According to several articles I've read (like this one), in order to dynamically add class methods to Ruby classes, you have to use the class's singleton class:

class Klass
end

class << Klass
  self.define_method(:foo) { return "foo" }
end

这是为什么,这与此有何不同?

Why is this, and how is that different from this?

class Klass
  self.define_method(:foo) { return "foo" }
end

(对不起,如果这个问题包含任何错误的假设.就像我说的,我有点困惑.)

(Sorry if this question contains any false assumptions. Like I said, I'm a bit confused.)

推荐答案

直接回答您的问题:Module#define_method 创建一个实例方法.类方法"是 Class 对象的单例类(或特征类)上的实例方法.我敢肯定这听起来很令人困惑.让我解释一下为什么 Ruby 首先包含单例类"的概念:

To answer your question directly: Module#define_method creates an instance method. A "class method" is an instance method on the singleton class (or eigenclass) of a Class object. I'm sure that sounds very confusing. Let me explain why Ruby includes the concept of "singleton classes" in the first place:

首先,让我说不同面向对象语言的基本框架"是多种多样的.Ruby 在对象、类、元类等方面的设计绝不是唯一可能的,而且该语言可以以不同的方式设计.话虽如此,Ruby 的工作方式是有逻辑的.我会尽量简明扼要地解释...

First, let me say that the basic "framework" of different object-oriented languages are quite varied. Ruby's design as regards objects, classes, metaclasses, etc. is by no means the only possible one, and the language could have been designed in a different way. Having said that, there are logical reasons why Ruby works the way it does. I'll try to explain as concisely as possible...

想想一个简单的方法调用,比如:

Think of a simple method call, like:

[1,2,3].first

这里我们调用了一个名为 first 的方法,以一个 Array 对象作为接收者.为了处理这个方法调用,Ruby 需要搜索匹配的方法定义并执行它.它从哪里开始寻找?自然,在Array的实例方法中.如果在那里没有找到,它会在Array的超类中查找,然后是超类的超类,以及混入Module>Array 或其超类等

Here we are calling a method called first, with an Array object as receiver. To process this method call, Ruby needs to search for a matching method definition, and execute it. Where does it start looking? Naturally, in the instance methods of Array. If it doesn't find it there, it will look in Array's superclass, then the superclass of the superclass, as well as Modules which are mixed into Array or its superclasses, etc.

基于类"(相对于基于原型)的面向对象语言或多或少都是这样工作的.如果您曾经使用 Java、C++ 或 Python 进行过编程,那么您应该很熟悉这种行为.

"Class-based" (as opposed to prototype-based) object-oriented languages all work this way, more or less. If you've ever programmed in Java, or C++, or Python, this behavior should be familiar to you.

现在,Ruby 的创建者还希望能够为仅一个对象添加方法.在基于原型的面向对象语言中,这很容易,但如何在基于类的语言中工作呢?他通过引入单例类"或特征类"的概念使之成为可能.

Now, the creator of Ruby wanted to also make it possible to add methods to just one object. In a prototype-based OO language, that would be easy, but how could it work in a class-based language? He made it possible by introducing the idea of "singleton classes" or "eigenclasses".

单例类"简单来说就是一个只有一个实例的类.我相信 Ruby 不会尝试为 每个 对象跟踪不同的单例类,而是等到您第一次尝试访问对象的单例类时,然后创建该类并将其插入到对象的继承链动态.

A "singleton class" is, simply, a class which has only one instance. I believe that rather than trying to keep track of a different singleton class for every single object, Ruby waits until the first time you try to access an object's singleton class, and then creates the class and inserts it into the object's inheritance chain dynamically.

正如我刚才所说,当一个方法被调用时,Ruby首先在对象的类中查找匹配的定义,然后是超类等.由于单例类作为第一个链接插入对象的继承链,它们是 Ruby 查找方法定义的第一个地方.

As I just said, when a method is called, Ruby looks first in the object's class to find a matching definition, then the superclass, etc. Since singleton classes are inserted as the first link in an object's inheritance chain, they are the first place which Ruby will look for a method definition.

引入单例类"的概念同时也解决了另一个问题.在 Java 中(例如),您可以定义在类上调用的 static 方法.在 Ruby 中,人们常常想做类似的事情.使用单例"类和方法,您可以做到这一点:您所要做的就是在 Class 对象上定义一个单例方法.

Bringing in the concept of "singleton classes" also solved another problem at the same time. In Java (for example), you can define static methods which are called on a class. In Ruby, people often want to do something similar. With "singleton" classes and methods, you can do just that: all you have to do is define a singleton method on a Class object.

(请记住,类在 Ruby 中也是对象.这就是为什么单例"类和方法的概念可以用 1 块石头杀死 2 只鸟",正如我上面解释的那样!)

(Remember that classes are also objects in Ruby. That's why the concept of "singleton" classes and methods can "kill 2 birds with 1 stone", as I explain above!)

额外信息:

一开始,我提到了实例方法".我不知道这是否会令人困惑,或者您是否已经知道什么是实例方法".当你定义一个 Ruby 类时,像这样...

At the beginning, I mentioned "instance methods". I don't know if that might be confusing, or if you already know what "instance methods" are. When you define a Ruby class, like this...

class MyClass
  def my_method
    # do something
  end
end

...那么my_method 将被添加为MyClass实例方法.当 Ruby 在对象的类、超类等中搜索方法定义时,它实际查看的是它们的实例方法.所以一个对象的方法"就是它的类的实例方法,加上超类的实例方法,超类的超类等等.

...then my_method will be added as an instance method of MyClass. When Ruby searches an object's class, superclass, etc. for a method definition, what it actually looks at are their instance methods. So an object's "methods" are the instance methods of its class, plus the instance methods of the superclass, the superclass of the superclass, etc.

关于单例类如何与 Ruby 中的方法查找交互,有一点我上面没有提到的不一致.如果你想详细了解:

About how singleton classes interact with method lookup in Ruby, there is a slight inconsistency which I didn't mention above. If you want to understand in detail:

类对象的单例类通常与其他对象的单例类的处理方式略有不同.如果你有一个类 A 从另一个类 B 继承,并且 B 有单例方法,A 将继承不只是实例方法,还有还有B 的单例方法.换句话说,B 的单例类被视为 A 的单例类的超类.对于任何其他对象的单例类,情况并非如此.

Singleton classes of class objects are treated a little differently from singleton classes of other objects in general. If you have a class A which inherits from another class B, and B has singleton methods, A will inherit not just the instance methods, but also the singleton methods of B. In other words, B's singleton class is treated as a superclass of A's singleton class. This is not true of the singleton classes of any other objects.

这篇关于Ruby 中的类和该类的单例之间有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆