类 Class
扩展任意 Class
以包含 json_creatable? 方法。
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)-----------...
公共类方法
使用给定的超类(如果没有给定参数,则为 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; }
公共实例方法
为 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); }
返回接收器是其单例类的对象。
如果类不是单例类,则引发 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); }
如果此类可用于从序列化 JSON
字符串创建实例,则返回 true。该类必须实现类方法 json_create,该方法将哈希作为第一个参数。哈希应包括所需数据。
# File ext/json/lib/json/common.rb, line 694 def json_creatable? respond_to?(:json_create) end
调用 allocate
以创建 class 类的对象,然后调用该对象的 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; }
返回一个类的数组,其中接收器是类的直接超类,不包括单例类。返回数组的顺序未定义。
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); }
返回 class 的超类,或 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; } }
私有实例方法
每当创建当前类的子类时调用的回调。
示例
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