如何在Ruby中复制嵌套类结构

时间:2012-12-14 16:31:38

标签: ruby class nested

假设我有一个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

我怎样才能做到这一点?提前谢谢。

2 个答案:

答案 0 :(得分: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部分可能与此代码不正确。

答案 1 :(得分: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.

如果要为两个类添加相同的代码,请创建一个模块并包含它。 Ruby创建一个指向模块的代理,并将代理插入从对象类到其超类的指针链中,这样搜索方法机制将在类的方法之后和之前的方法之前查找模块的方法。超类。

class D
   extend A
end

将A的实例方法定义为D的类(单例)方法。听起来很难看。我认为你应该试验,展示puts,p,instance_methods,singleton_methods等会发生什么。