Feature #6682 ยป class_singleton_instance.patch
| NEWS | ||
|---|---|---|
|
* extended method:
|
||
|
* Module#define_method accepts a UnboundMethod from a Module.
|
||
|
* Class
|
||
|
* added method:
|
||
|
* added Class#singleton_instance returning the attached instance from a
|
||
|
singleton Class. This is the reversed version of the
|
||
|
Kernel#singleton_class getter method.
|
||
|
* NilClass
|
||
|
* added method:
|
||
|
* added nil.to_h which returns {}
|
||
| class.c | ||
|---|---|---|
|
return Qnil;
|
||
|
}
|
||
|
static inline VALUE
|
||
|
special_singleton_instance_of(VALUE obj)
|
||
|
{
|
||
|
SPECIAL_SINGLETON(rb_cNilClass, Qnil);
|
||
|
SPECIAL_SINGLETON(rb_cFalseClass, Qfalse);
|
||
|
SPECIAL_SINGLETON(rb_cTrueClass, Qtrue);
|
||
|
rb_raise(rb_eTypeError, "not singleton class");
|
||
|
}
|
||
|
VALUE
|
||
|
rb_special_singleton_class(VALUE obj)
|
||
|
{
|
||
|
return special_singleton_class_of(obj);
|
||
|
}
|
||
|
VALUE
|
||
|
rb_special_singleton_instance(VALUE obj)
|
||
|
{
|
||
|
return special_singleton_instance_of(obj);
|
||
|
}
|
||
|
/*!
|
||
|
* \internal
|
||
|
* Returns the singleton class of \a obj. Creates it if necessary.
|
||
| internal.h | ||
|---|---|---|
|
VALUE rb_obj_public_methods(int argc, VALUE *argv, VALUE obj);
|
||
|
int rb_obj_basic_to_s_p(VALUE);
|
||
|
VALUE rb_special_singleton_class(VALUE);
|
||
|
VALUE rb_special_singleton_instance(VALUE);
|
||
|
void Init_class_hierarchy(void);
|
||
|
/* compile.c */
|
||
| object.c | ||
|---|---|---|
|
return super;
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* class.singleton_instance -> an_object
|
||
|
*
|
||
|
* Returns the attached singleton instance of <i>class</i>.
|
||
|
*
|
||
|
* klass = "Hello".singleton_class
|
||
|
* klass.singleton_instance => "Hello"
|
||
|
*
|
||
|
* If the given class isn't a singleton class, it raises a TypeError.
|
||
|
*
|
||
|
*/
|
||
|
VALUE
|
||
|
rb_class_singleton_instance(VALUE klass)
|
||
|
{
|
||
|
if(FL_TEST(klass, FL_SINGLETON)) {
|
||
|
return rb_iv_get(klass, "__attached__");
|
||
|
} else {
|
||
|
return rb_special_singleton_instance(klass);
|
||
|
}
|
||
|
}
|
||
|
VALUE
|
||
|
rb_class_get_superclass(VALUE klass)
|
||
|
{
|
||
| ... | ... | |
|
rb_define_method(rb_cClass, "initialize", rb_class_initialize, -1);
|
||
|
rb_define_method(rb_cClass, "initialize_copy", rb_class_init_copy, 1); /* in class.c */
|
||
|
rb_define_method(rb_cClass, "superclass", rb_class_superclass, 0);
|
||
|
rb_define_method(rb_cClass, "singleton_instance", rb_class_singleton_instance, 0);
|
||
|
rb_define_alloc_func(rb_cClass, rb_class_s_alloc);
|
||
|
rb_undef_method(rb_cClass, "extend_object");
|
||
|
rb_undef_method(rb_cClass, "append_features");
|
||
| test/ruby/test_class.rb | ||
|---|---|---|
|
INPUT
|
||
|
end
|
||
|
def test_singleton_instance
|
||
|
o = Object.new
|
||
|
c = o.singleton_class
|
||
|
assert_equal(o, c.singleton_instance)
|
||
|
end
|
||
|
def test_no_singleton_instance
|
||
|
assert_raise(TypeError) { String.singleton_instance }
|
||
|
end
|
||
|
def test_class_singleton_instance
|
||
|
c = Object.singleton_class
|
||
|
assert_equal(Object, c.singleton_instance)
|
||
|
end
|
||
|
def test_immediate_singleton_instance
|
||
|
assert_equal(true, TrueClass.singleton_instance)
|
||
|
assert_equal(false, FalseClass.singleton_instance)
|
||
|
assert_equal(nil, NilClass.singleton_instance)
|
||
|
end
|
||
|
def test_uninitialized
|
||
|
assert_raise(TypeError) { Class.allocate.new }
|
||
|
assert_raise(TypeError) { Class.allocate.superclass }
|
||