類別 Class

延伸任何 類別 以包含 json_creatable? 方法。

Ruby 中的類別是一等物件,每個類別都是 類別 類別的實例。

通常,您可以使用以下方式建立新類別

class Name
 # some code describing the class behavior
end

當建立新類別時,會初始化 類別 類型的物件,並將其指定給全域常數(此例中為 Name)。

當呼叫 Name.new 來建立新物件時,預設會執行 類別 中的 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

類別、模組和物件是相互關聯的。在以下圖表中,垂直箭頭表示繼承,括號表示元類別。所有元類別都是「類別」類別的實例。

                         +---------+             +-...
                         |         |             |
         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 (!FL_TEST(klass, FL_SINGLETON)) {
        rb_raise(rb_eTypeError, "`%"PRIsVALUE"' is not a singleton class", klass);
    }

    return RCLASS_ATTACHED_OBJECT(klass);
}
json_creatable?() 按一下以切換來源

如果這個類別可以用來從序列化 JSON 字串建立實例,則傳回 true。類別必須實作類別方法 json_create,它預期雜湊作為第一個參數。雜湊應包含必要的資料。

# File ext/json/lib/json/common.rb, line 694
def json_creatable?
  respond_to?(:json_create)
end
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