类 Class
在 Ruby 中,类是一等公民——每个类都是 Class
类的实例。
通常,使用以下方式创建新类:
class Name # some code describing the class behavior end
当创建新类时,会初始化一个 Class
类型的对象,并将其分配给一个全局常量(本例中为 Name)。
当调用 Name.new
创建新对象时,默认情况下会运行 Class
中的 new
方法。可以通过在 Class 中重写 new
方法来演示这一点。
class Class alias old_new new def new(*args) print "Creating a new ", self.name, "\n" old_new(*args) end end class Name end n = Name.new
输出结果为:
Creating a new Name
类、模块和对象之间相互关联。在下图中,垂直箭头表示继承关系,括号表示元类。所有元类都是 ‘Class’ 类的实例。
+---------+ +-... | | | BasicObject-----|-->(BasicObject)-------|-... ^ | ^ | | | | | Object---------|----->(Object)---------|-... ^ | ^ | | | | | +-------+ | +--------+ | | | | | | | | Module-|---------|--->(Module)-|-... | ^ | | ^ | | | | | | | | Class-|---------|---->(Class)-|-... | ^ | | ^ | | +---+ | +----+ | | obj--->OtherClass---------->(OtherClass)-----------...
公共类方法
new(super_class=Object) → a_class 点击切换源代码
new(super_class=Object) { |mod| ... } → a_class
创建一个新的匿名(无名)类,其父类为给定的 super_class(如果没有参数,则为 Object
)。可以通过将类对象分配给一个常量来为类命名。
如果提供了代码块,则将类对象传递给代码块,并且代码块将在该类的上下文中执行,类似于 class_eval
。
fred = Class.new do def meth1 "hello" end def meth2 "bye" end end a = fred.new #=> #<#<Class:0x100381890>:0x100376b98> a.meth1 #=> "hello" a.meth2 #=> "bye"
如果要将类像普通类一样对待,则将其分配给一个常量(以大写字母开头的名称)。
static VALUE rb_class_initialize(int argc, VALUE *argv, VALUE klass) { VALUE super; if (RCLASS_SUPER(klass) != 0 || klass == rb_cBasicObject) { rb_raise(rb_eTypeError, "already initialized class"); } if (rb_check_arity(argc, 0, 1) == 0) { super = rb_cObject; } else { super = argv[0]; rb_check_inheritable(super); if (super != rb_cBasicObject && !RCLASS_SUPER(super)) { rb_raise(rb_eTypeError, "can't inherit uninitialized class"); } } RCLASS_SET_SUPER(klass, super); rb_make_metaclass(klass, RBASIC(super)->klass); rb_class_inherited(super, klass); rb_mod_initialize_exec(klass); return klass; }
公共实例方法
allocate() → obj 点击切换源代码
为 class 类的新的对象分配空间,但不调用新实例的 initialize 方法。返回的对象必须是 class 的实例。
klass = Class.new do def initialize(*args) @initialized = true end def initialized? @initialized || false end end klass.allocate.initialized? #=> false
static VALUE rb_class_alloc_m(VALUE klass) { rb_alloc_func_t allocator = class_get_alloc_func(klass); if (!rb_obj_respond_to(klass, rb_intern("allocate"), 1)) { rb_raise(rb_eTypeError, "calling %"PRIsVALUE".allocate is prohibited", klass); } return class_call_alloc_func(allocator, klass); }
attached_object → object 点击切换源代码
返回接收者是单例类的对象。
如果该类不是单例类,则引发 TypeError
。
class Foo; end Foo.singleton_class.attached_object #=> Foo Foo.attached_object #=> TypeError: `Foo' is not a singleton class Foo.new.singleton_class.attached_object #=> #<Foo:0x000000010491a370> TrueClass.attached_object #=> TypeError: `TrueClass' is not a singleton class NilClass.attached_object #=> TypeError: `NilClass' is not a singleton class
VALUE rb_class_attached_object(VALUE klass) { if (!FL_TEST(klass, FL_SINGLETON)) { rb_raise(rb_eTypeError, "`%"PRIsVALUE"' is not a singleton class", klass); } return RCLASS_ATTACHED_OBJECT(klass); }
new(args, ...) → obj 点击切换源代码
调用 allocate
创建一个类类的新对象,然后调用该对象的初始化方法,并将args传递给它。这是在使用.new
构造对象时最终被调用的方法。
VALUE rb_class_new_instance_pass_kw(int argc, const VALUE *argv, VALUE klass) { VALUE obj; obj = rb_class_alloc(klass); rb_obj_call_init_kw(obj, argc, argv, RB_PASS_CALLED_KEYWORDS); return obj; }
subclasses → array 点击切换源代码
返回一个类数组,其中接收方是类的直接超类,不包括单例类。返回数组的顺序未定义。
class A; end class B < A; end class C < B; end class D < A; end A.subclasses #=> [D, B] B.subclasses #=> [C] C.subclasses #=> []
匿名子类(未与常量关联)也会被返回。
c = Class.new(A) A.subclasses # => [#<Class:0x00007f003c77bd78>, D, B]
请注意,父类不保存对子类的引用,也不阻止它们被垃圾回收。这意味着当所有对子类的引用都被删除时,子类可能会消失。
# drop the reference to subclass, it can be garbage-collected now c = nil A.subclasses # It can be # => [#<Class:0x00007f003c77bd78>, D, B] # ...or just # => [D, B] # ...depending on whether garbage collector was run
VALUE rb_class_subclasses(VALUE klass) { return class_descendants(klass, true); }
superclass → a_super_class or nil 点击切换源代码
返回类的超类,或nil
。
File.superclass #=> IO IO.superclass #=> Object Object.superclass #=> BasicObject class Foo; end class Bar < Foo; end Bar.superclass #=> Foo
当给定类没有父类时,返回 nil。
BasicObject.superclass #=> nil
VALUE rb_class_superclass(VALUE klass) { RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS)); VALUE super = RCLASS_SUPER(klass); if (!super) { if (klass == rb_cBasicObject) return Qnil; rb_raise(rb_eTypeError, "uninitialized class"); } if (!RCLASS_SUPERCLASS_DEPTH(klass)) { return Qnil; } else { super = RCLASS_SUPERCLASSES(klass)[RCLASS_SUPERCLASS_DEPTH(klass) - 1]; RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS)); return super; } }
私有实例方法
inherited(subclass) 点击切换源代码
每当创建当前类的子类时,都会调用回调。
示例
class Foo def self.inherited(subclass) puts "New subclass: #{subclass}" end end class Bar < Foo end class Baz < Bar end
输出结果为:
New subclass: Bar New subclass: Baz
#define rb_obj_class_inherited rb_obj_dummy1