【问题标题】:Ruby metaclasses class hierarchyRuby 元类类层次结构
【发布时间】:2013-09-17 20:42:33
【问题描述】:

This post 关于元类及其在 Ruby 对象模型中的位置有一个类层次图。其中Class:ClassClass的单例类)是它自己的一个实例,但我认为它应该是Class的一个实例。换句话说,如果我们有对象class_singletonclass如下:

class_singletonclass = Class.singleton_class
# => #<Class:Class>

它的内部类指针klass 指向哪里?在Class的情况下klass指向哪里,假设我们为Class定义了一个类方法(单例方法)?

我意识到Class 已经定义了类方法。我猜Class 很特别,并且在 MRI 中有自己的 C 实现,因此添加类方法将创建一个适当的元类。这个假设是错误的吗?

我在 MRI 中的 class.c 中发现了以下内容:

/*!
 * A utility function that wraps class_alloc.
 *
 * allocates a class and initializes safely.
 * \param super     a class from which the new class derives.
 * \return          a class object.
 * \pre  \a super must be a class.
 * \post the metaclass of the new class is Class.
 */
VALUE
rb_class_boot(VALUE super)
{
    VALUE klass = class_alloc(T_CLASS, rb_cClass);

    RCLASS_SET_SUPER(klass, super);
    RCLASS_M_TBL(klass) = st_init_numtable();

    OBJ_INFECT(klass, super);
    return (VALUE)klass;
}

\post the metaclass of the new class is Class. 这一行表明Class 的元类确实是Class,这适用于所有元类。

【问题讨论】:

  • 可能值得制作自己的图表版本。我对您的问题的理解是“元类&lt;Class&gt;(蓝色)上的环回虚线(代表instance of)实际上不应循环到自身,而应指向普通Class(绿色),对吗?” - 我几乎不明白这一点,这无济于事,但我目前在浏览您的问题时遇到了一些问题。
  • 是的,这就是我想说的。对不起,如果我的措辞太混乱了。
  • 它试图解开令人困惑的“类”这个词的许多区别。我认为要清楚地写出这个主题需要付出巨大的努力。

标签: ruby metaprogramming


【解决方案1】:

我已将上面链接的帖子中的 inheritance 扩展改编为 Ruby 2.0:

inheritance.c

#include "ruby.h"

VALUE real_super(VALUE self)
{
  return RCLASS_SUPER(RBASIC(self)->klass);
}

VALUE real_klass(VALUE self)
{
  return RBASIC(self)->klass;
}

void Init_inheritance()
{
  rb_define_method(rb_cClass,"real_super",real_super,0);
  rb_define_method(rb_cClass,"real_klass",real_klass,0);
}

test.rb

require_relative 'inheritance'

puts "Object real class: #{Object.real_klass}"
puts "Object real superclass: #{Object.real_super}"

puts "Class real class: #{Class.real_klass}"
puts "Class real superclass: #{Class.real_super}"

puts "Class metaclass real class: #{Class.singleton_class.real_klass}"
puts "Class metaclass real superclass: #{Class.singleton_class.real_super}"

puts "Object metaclass real class: #{Object.singleton_class.real_klass}"
puts "Object metaclass real superclass: #{Object.singleton_class.real_super}"

puts "An object singleton class real class: #{Object.new.singleton_class.real_klass}"
puts "An object singleton class real superclass: #{Object.new.singleton_class.real_super}"

输出是:

Object real class: #<Class:Object>
Object real superclass: #<Class:BasicObject>
Class real class: #<Class:Class>
Class real superclass: #<Class:Module>
Class metaclass real class: #<Class:#<Class:Class>>
Class metaclass real superclass: #<Class:#<Class:Module>>
Object metaclass real class: #<Class:#<Class:Object>>
Object metaclass real superclass: #<Class:#<Class:BasicObject>>
An object singleton class real class: #<Class:Object>
An object singleton class real superclass: #<Class:BasicObject>

所以在元类的情况下,klass 指向元类本身(图的那部分是正确的,但指向和 中的一些不一致)。

【讨论】:

  • 我的回答有点匆忙,所以我只是想澄清一下。图表中正确的部分是指出Class:Class 是其自身的一个实例,但由于这适用于所有元类(即元类是其自身的一个实例),所以图表中关于Class:Object 的部分和Class:Module 不正确,至少对于 Ruby 2.0。
  • 另外,class.c 中的 cmets 应该被解释为 Ruby 语义而不是实现。从 Ruby 的角度来看,元类是在类层次结构中遍历的匿名类。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-12-04
  • 2017-02-22
  • 2011-05-19
  • 1970-01-01
  • 2017-01-24
  • 2019-01-09
  • 2017-09-25
相关资源
最近更新 更多