$B<G$H?=$7$^$9!#(B
$B%/%i%9%*%V%8%’%/%H$r(B clone
$B$7$?$H$-$N5sF0$K$D$$$F<ALd$5$;$F$/$@$5$$!#(B
$B%5%s%W%k%3!<%I(B
String.class_eval do
def self.singleton_method_added(mid)
puts(“singleton_method_added: self = #{self}, mid = #{mid}”)
end
end
puts(“start clone”)
StrClone = String.clone
puts(“finish clone”)
$B%5%s%W%k%3!<%I$N<B9T7k2L(B
singleton_method_added: self = String, mid = singleton_method_added
start clone
singleton_method_added: self = String, mid = try_convert
singleton_method_added: self = String, mid = singleton_method_added
finish clone
$B>e5-$N%5%s%W%k%3!<%I$r<B9T$9$k$H!"(BString $B%/%i%9$r(B clone
$B$7!"%a%=%C%I%F!<(B
$B%V%k$r(B StrClone $B$K%3%T!<$7$F$$$k$H$-$K!"(BString
$B%/%i%9$KBP$7$F(B
singleton_method_added $B$,8F$S=P$5$l!"<B9T7k2L$N$h$&$K=PNO$5$l$^$9!#(B
$B<ALd$J$s$G$9$,!"%/%i%9%%V%8%’%/%H$N(B clone $B;~$K(B clone
$B85$N%/%i%9%%V%8%’(B
$B%/%H$N(B singleton_method_added
$B$,8F$S=P$5$l$k$N$O;EMM$J$N$G$7$g$&$+!#(B
$B>e5-$N%5%s%W%k%3!<%I$N>l9g!"(BStrClone $B$N(B singleton_method_added
$B$,8F$S=P(B
$B$5$l$k$+!"$b$7$/$O(B singleton_method_added
$B$,8F$S=P$5$l$J$$$3$H$r4|BT$7$F(B
singleton_method_added $B$r;HMQ$7$F$$$^$7$?!#(B
$B>e5-$N%5%s%W%k%3!<%I$G(B String $B%/%i%9$N(B singleton_method_added
$B$,8F$S=P$5(B
$B$l$k860x$O!"(Brb_singleton_class_clone(class.c) $B$K$"$j$^$9!#(B
rb_singleton_class_clone
$B$G$O!“0J2<$N$h$&$KFC0[%/%i%9$N%$%s%9%?%s%9JQ?t(B
$B$r%3%T!<$9$k$N$G$9$,!”$3$N$H$-!"(B"attached"
$B$H$$$&%$%s%9%?%s%9JQ?t$r(B
$B%3%T!<$7$F$$$^$9!#(B
VALUE
rb_singleton_class_clone(VALUE obj)
{
…
if (RCLASS_IV_TBL(klass)) {
/* $B%$%s%9%?%s%9JQ?t$N%3%T!<(B /
RCLASS_IV_TBL(clone) = st_copy(RCLASS_IV_TBL(klass));
}
…
RCLASS_M_TBL(clone) = st_init_numtable();
data.tbl = RCLASS_M_TBL(clone);
data.klass = (VALUE)clone;
/ $B%a%=%C%I%F!<%V%k$N%3%T!<!"(Bmethod_added $B$N8F$S=P$7(B */
st_foreach(RCLASS_M_TBL(klass), clone_method,
(st_data_t)&data);
…
}
$B:#2s$NNc$N>l9g!"$3$N!"(B"attached" $B$O!"%/%i%9$N%3%T!<85$G$"$k(B
String
$B%/%i%9$r;X$7$F$$$^$9!#(Bsingleton_method_added $B$r8F$S=P$9(B
CALL_METHOD_HOOK
$B$G$O!“0J2<$N$h$&$K!”%l%7!<%P$rFC0[%/%i%9$N(B “attached”
$B$K$h$C$F7hDj$9(B
$B$k$N$G!"%a%=%C%I%F!<%V%k$r%3%T!<$9$k$H$-$K8F$S=P$9(B
singleton_method_added $B$N%l%7!<%P$,!"(BString $B$K$J$C$F$$$^$9!#(B
#define CALL_METHOD_HOOK(klass, hook, mid) do {
const VALUE arg = ID2SYM(mid);
VALUE recv_class = (klass);
ID hook_id = (hook);
if (FL_TEST((klass), FL_SINGLETON)) {
recv_class = rb_ivar_get((klass), attached);
hook_id = singleton_##hook;
}
rb_funcall2(recv_class, hook_id, 1, &arg);
} while (0)
$B$3$N$h$&$K$J$k$N$,;EMM$H$7$FDj$^$C$F$$$k$N$+$I$&$+$,J,$+$i$J$$$N$G$9$,!"(B
singleton_method_added
$B$N%l%7!<%P$r%/%m!<%s@h$N%/%i%9$KJQ99$9$k$h$&$K$7(B
$B$?%Q%C%A$r:n@.$7$?$N$G!“K%a!<%k$NKvHx$KD%$C$F$*$-$^$9!#(B
rb_obj_clone $B$G$N(B
RBASIC(clone)->klass = rb_singleton_class_clone_and_attach(obj, clone);
$B$N0LCV$r$:$i$7$F$$$$$N$+$I$&$+$,IT0B$J$s$G$9$,!”;29M$K$7$F$$$?$@$1$l$P9,(B
$B$$$G$9!#(B
$B0J>e!"$h$m$7$/$*4j$$$$$?$7$^$9!#(B
$B%Q%C%A(B
Index: object.c
— object.c (revision 33202)
+++ object.c (working copy)
@@ -268,6 +268,7 @@
- the class.
*/
+VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
VALUE
rb_obj_clone(VALUE obj)
{
@@ -277,9 +278,9 @@
rb_raise(rb_eTypeError, “can’t clone %s”,
rb_obj_classname(obj));
}
clone = rb_obj_alloc(rb_obj_class(obj));
- RBASIC(clone)->klass = rb_singleton_class_clone(obj);
RBASIC(clone)->flags = (RBASIC(obj)->flags | FL_TEST(clone,
FL_TAINT) | FL_TEST(clone, FL_UNTRUSTED)) &
~(FL_FREEZE|FL_FINALIZE|FL_MARK);
init_copy(clone, obj);
- RBASIC(clone)->klass = rb_singleton_class_clone_and_attach(obj,
clone);
rb_funcall(clone, id_init_clone, 1, obj);
RBASIC(clone)->flags |= RBASIC(obj)->flags & FL_FREEZE;
Index: class.c
— class.c (revision 33202)
+++ class.c (working copy)
@@ -219,9 +219,17 @@
return rb_mod_init_copy(clone, orig);
}
+VALUE rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach);
+
VALUE
rb_singleton_class_clone(VALUE obj)
{
- return rb_singleton_class_clone_and_attach(obj, Qundef);
+}
+VALUE
+rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach)
+{
VALUE klass = RBASIC(obj)->klass;
if (!FL_TEST(klass, FL_SINGLETON))
@@ -246,6 +254,10 @@
RCLASS_CONST_TBL(clone) = st_init_numtable();
st_foreach(RCLASS_CONST_TBL(klass), clone_const_i,
(st_data_t)RCLASS_CONST_TBL(clone));
}
-
if (attach != Qundef) {
-
rb_singleton_class_attached(clone, attach);
-
} RCLASS_M_TBL(clone) = st_init_numtable(); data.tbl = RCLASS_M_TBL(clone); data.klass = (VALUE)clone;