1

次のようなクラス A があるとします。

class A
  class B
  end
  class C < B
  end
  ...
end

そして、Aと同じネストされたクラス構造を持つクラスDを作成したい

class D
  Replicate nested class structure of A here
end

私はDを次のようにしたい:

class D
  class B
  end
  class C < B
  end
  ...
end

A::B と D::B を異なる結果で実行できるように

どうすればこれを達成できますか?前もって感謝します。

4

2 に答える 2

2
class Module
  def replicate m
    m.constants.each do |sym|
      case mm = m.const_get(sym)
      when Class then const_set(sym, Class.new(mm.superclass)).replicate(mm)
      when Module then const_set(sym, Module.new(mm.superclass)).replicate(mm)
      end
    end
  end
end

class D
  replicate A
end

ただし、superclassこのコードではパーツが正しくない可能性があります。

于 2012-12-14T18:21:26.703 に答える
1
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などで何が起こるかを実験して表示する必要があると思います。

于 2012-12-14T18:39:57.723 に答える