Ruby 类方法与特征类中的方法
类方法和该类的特征类(或元类)中的方法只是定义一件事的两种方法吗?
否则的话,有什么区别呢?
class X
# class method
def self.a
"a"
end
# eigenclass method
class << self
def b
"b"
end
end
end
Xa
和 Xb
的行为有什么不同吗?
我认识到我可以通过打开特征类来覆盖或别名类方法:
irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"
Are class methods and methods in the eigenclass (or metaclass) of that class just two ways to define one thing?
Otherwise, what are the differences?
class X
# class method
def self.a
"a"
end
# eigenclass method
class << self
def b
"b"
end
end
end
Do X.a
and X.b
behave differently in any way?
I recognize that I can overwrite or alias class methods by opening the eigenclass:
irb(main):031:0> class X; def self.a; "a"; end; end
=> nil
irb(main):032:0> class X; class << self; alias_method :b, :a; end; end
=> #<Class:X>
irb(main):033:0> X.a
=> "a"
irb(main):034:0> X.b
=> "a"
irb(main):035:0> class X; class << self; def a; "c"; end; end; end
=> nil
irb(main):036:0> X.a
=> "c"
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
这两种方法是等效的。 “eigenclass”版本对于使用 attr_* 方法很有帮助,例如:
您还可以使用
define_singleton_method
在类上创建方法:The two methods are equivalent. The 'eigenclass' version is helpful for using the attr_* methods, for example:
You can also use
define_singleton_method
to create methods on the class:在 Ruby 中,确实不存在类方法之类的东西。由于 Ruby 中的一切都是对象(包括类),因此当您说
def self.class_method
时,您实际上只是在类Class
的实例上定义了一个单例方法。所以回答你的问题,说是说同一件事的两种方式。这两个方法都只是在 Class 对象的实例中定义的单一(eigen、meta、ghost 或任何您想调用的名称)方法,在您的示例中为
X
。本主题是元编程的一部分,这是一个有趣的主题,如果您已经使用 Ruby 一段时间,那么您应该查看一下。Pragmatic Programmers 有一本很棒的关于元编程的书,如果您对元编程感兴趣,您绝对应该看一下话题。
In Ruby there really are no such things as class methods. Since everything is an object in Ruby (including classes), when you say
def self.class_method
, you are just really defining a singleton method on the instance of the classClass
. So to answer your question, sayingis two ways of saying the same thing. Both these methods are just singeton (eigen, meta, ghost, or whatever you want to call them) methods defined in the instance of your Class object, which in your example was
X
. This topic is part of metaprogramming, which is a fun topic, that if you have been using Ruby for a while, you should check out.The Pragmatic Programmers have a great book on metaprogramming that you should definitely take a look at if you interested in the topic.
另一位死灵法师在这里挖掘这个老问题...您可能不知道的一件事是将类方法标记为
private
(使用 private 关键字而不是:private_class_method
) 与标记特征类方法不同。 :以下示例将按照上一个示例的方式工作:
Yet another necromancer here to unearth this old question... One thing you might not be aware of is that marking a class method as
private
(using the private keyword instead of:private_class_method
) is different than marking an eigenclass method as such. :The following example will work how the previous one intends:
Ruby 中使用的大多数实例方法都是全局方法。这意味着它们在定义它们的类的所有实例中都可用。相反,单例方法是在单个对象上实现的。
存在明显的矛盾。 Ruby 将方法存储在类中,并且所有方法都必须与类关联。定义单例方法的对象不是类(它是类的实例)。如果只有类才能存储方法,那么对象怎么能存储单例方法呢?创建单例方法时,Ruby 会自动创建一个匿名类来存储该方法。这些匿名类称为元类,也称为单例类或特征类。单例方法与元类相关联,元类又与定义单例方法的对象相关联。
如果在单个对象中定义了多个单例方法,则它们都存储在同一个元类中。
在上面的示例中,say_hello 方法是在 Zen 类的 z1 实例中定义的,而不是在 z2 实例中定义的。
以下示例显示了定义单例方法的不同方法,但具有相同的结果。
在上面的例子中,class << z1 改变当前 self 指向 z1 对象的元类;然后,它在元类中定义 say_hello 方法。
上面的两个例子都说明了单例方法是如何工作的。然而,有一种更简单的方法来定义单例方法:使用名为 Define_singleton_method 的内置方法。
我们之前了解到类也是对象(称为 Class 的内置类的实例)。我们还了解了类方法。 类方法只不过是与类对象关联的单例方法。
再举一个例子:
所有对象都可能具有元类。这意味着类也可以有元类。在上面的例子中,class << self 修改 self,使其指向 Zabuton 类的元类。当一个方法在没有显式接收者(将在其上定义该方法的类/对象)的情况下定义时,它会在当前范围内隐式定义,即 self 的当前值。因此,stuff 方法是在 Zabuton 类的元类中定义的。上面的示例只是定义类方法的另一种方式。
阅读这篇关于 Ruby 类的文章了解更多信息。
Most instance methods used in Ruby are global methods. That means they are available in all instances of the class on which they were defined. In contrast, a singleton method is implemented on a single object.
There is an apparent contradiction. Ruby stores methods in classes and all methods must be associated with a class. The object on which a singleton method is defined is not a class (it is an instance of a class). If only classes can store methods, how can an object store a singleton method? When a singleton method is created, Ruby automatically creates an anonymous class to store that method. These anonymous classes are called metaclasses, also known as singleton classes or eigenclasses. The singleton method is associated with the metaclass which, in turn, is associated with the object on which the singleton method was defined.
If multiple singleton methods are defined within a single object, they are all stored in the same metaclass.
In the above example, the say_hello method was defined within the z1 instance of the Zen class but not the z2 instance.
The following example shows a different way to define a singleton method, with the same result.
In the above example, class << z1 changes the current self to point to the metaclass of the z1 object; then, it defines the say_hello method within the metaclass.
Both of the above examples serve to illustrate how singleton methods work. There is, however, an easier way to define a singleton method: using a built-in method called define_singleton_method.
We learned earlier that classes are also objects (instances of the built-in class called Class). We also learned about class methods. Class methods are nothing more than singleton methods associated with a class object.
One more example:
All objects may have metaclasses. That means classes can also have metaclasses. In the above example, class << self modifies self so it points to the metaclass of the Zabuton class. When a method is defined without an explicit receiver (the class/object on which the method will be defined), it is implicitly defined within the current scope, that is, the current value of self. Hence, the stuff method is defined within the metaclass of the Zabuton class. The above example is just another way to define a class method.
Read more at this post about Ruby Classes.