From: Kouhei Sutou Date: 2008-05-10T22:30:13+09:00 Subject: [ruby-dev:34636] [ruby_1_8] Class#inheritedの呼ばれるタイミング 須藤です。 Class#inheritedが定義されていると継承した時に呼び出されます が、ruby_1_8ではブロック付きで無名クラスを定義したときの挙動 がおかしい気がします。 % ruby -e ' class A def A.inherited(sub) p :A end end Class.new(A) do p :anonymous end ' :anonymous :A trunkではブロックが評価される前にinheritedが呼ばれます。 % ruby1.9 -e ' class A def A.inherited(sub) p :A end end Class.new(A) do p :anonymous end ' :A :anonymous 通常のクラス定義ではclass ... end内が実行される前にinherited が呼ばれることを考えると、trunkでの挙動の方が自然な気がしま す。 ちなみに、trunkでこの修正が行われたのは2005-03-04のr8068ので かいコミットの中です。 Index: object.c =================================================================== --- object.c (revision 16346) +++ object.c (working copy) @@ -1564,8 +1564,8 @@ } RCLASS(klass)->super = super; rb_make_metaclass(klass, RBASIC(super)->klass); + rb_class_inherited(super, klass); rb_mod_initialize(klass); - rb_class_inherited(super, klass); return klass; } Index: test/ruby/test_class.rb =================================================================== --- test/ruby/test_class.rb (revision 0) +++ test/ruby/test_class.rb (revision 0) @@ -0,0 +1,34 @@ +require 'test/unit' + +class TestClass < Test::Unit::TestCase + class InheritedDetector + @@sub_classes = [] + class << self + def sub_classes + @@sub_classes + end + + def inherited(sub) + @@sub_classes << sub + end + end + end + + class InheritedClass < InheritedDetector + end + + def test_s_inherited + assert_equal([InheritedClass], InheritedDetector.sub_classes) + inherited_class = Class.new(InheritedDetector) + assert_equal([InheritedClass, inherited_class], + InheritedDetector.sub_classes) + sub_classes_snapshot = nil + inherited_class_with_block = Class.new(InheritedDetector) do + sub_classes_snapshot = InheritedDetector.sub_classes.dup + end + assert_equal([InheritedClass, inherited_class, inherited_class_with_block], + InheritedDetector.sub_classes) + assert_equal([InheritedClass, inherited_class, inherited_class_with_block], + sub_classes_snapshot) + end +end