class A
end
class D
end
[A, D].each do |c|
c.class_eval %Q(
class B
def bar; puts "B#bar in #{c} is not shared" end # <--- new
end
class C < B
def foo; puts "C#foo in #{c}" end
end
)
end
p A.constants
p A::C.instance_methods(false)
p D.constants
p D::C.instance_methods(false)
A::C.new.foo
D::C.new.foo
新しい
A::B.new.bar
D::B.new.bar
=begin
class B # creates a new class B
def quux; puts "A::B#quux in #{self}" end
end
A::B.new.quux #=> undefined method `quux' for #<A::B:0x101358a98> (NoMethodError)
=end
class A::B # reopens B in A
def quux; puts "A::B#quux in #{self}" end
end
A::B.new.quux
実行:
$ ruby -w t.rb
["B", "C"]
["foo"]
["B", "C"]
["foo"]
C#foo in A
C#foo in D
新しい
B#bar in A is not shared
B#bar in D is not shared
A::B#quux in #<A::B:0x10402da28>
メソッドや可能な変数を含む内部構造全体を複製するよりも複製します。このためには、熟考する必要があります。
新規:%Q()内のテキストに何かを入れると、class_evalはクラスごとにそれを評価するため、共有されません。Bは独立しておらず、A::BとD::Bの2つの異なるクラスがあります。
両方のクラスに同じコードを追加する場合は、モジュールを作成してインクルードします。Rubyは、モジュールを指すプロキシを作成し、オブジェクトのクラスからそのスーパークラスへのポインターのチェーンにプロキシを挿入します。これにより、検索メソッドメカニズムは、クラスのメソッドの後、およびメソッドの前にモジュールのメソッドを検索します。スーパークラス。
class D
extend A
end
AのインスタンスメソッドをDのクラス(シングルトン)メソッドとして定義します。醜く聞こえます。puts、p、instance_methods、singleton_methodsなどで何が起こるかを実験して表示する必要があると思います。