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 等会发生什么。