类 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
创建一个具有给定超类(如果没有给出参数,则为 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 点击切换源代码
为类的类的新对象分配空间,并且不调用新实例的 initialize 方法。返回的对象必须是类的一个实例。
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 (!RCLASS_SINGLETON_P(klass)) { rb_raise(rb_eTypeError, "'%"PRIsVALUE"' is not a singleton class", klass); } return RCLASS_ATTACHED_OBJECT(klass); }
new(args, ...) → obj 点击切换源代码
调用 allocate
来创建一个新的 类 的类的对象,然后调用该对象的 initialize 方法,并传入 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