2

为什么下面的例子有错误?

class ClassA
  class ClassB
  end
  class ClassC
    def test
      ClassB.new
    end
  end
end

p ClassA::ClassC.new.test # => #<ClassA::ClassB:0x0000010103f860>

class ClassA
  class ClassD
    def test
      ClassB.new
    end
  end
end

p ClassA::ClassD.new.test # => #<ClassA::ClassB:0x0000010103f010>

class ClassA::ClassE
  def test
    ClassB.new
  end
end

p ClassA::ClassE.new.test # => NameError: uninitialized constant ClassA::ClassE::ClassB

是否有另一种创建方式ClassE,而不是通过键入class ClassA; class ClassE

4

2 回答 2

1

好吧,是的,如果您定义要返回的测试方法ClassA::ClassB.new:-)

你也可以玩弄const_missing它,让它调用ClassA.const_get.

否则ClassB不在当前范围内,此时只有ClassA::ClassEand Object。当您第一次打开ClassA时,首先在 中进行ClassE查找,然后在(找到它的位置)进行查找,并且还会在 中查找。ClassBClassA::ClassEClassAObject

于 2010-07-22T20:08:30.340 回答
0

Marc-André Lafortune建议的自定义Object#const_missing方法将是

def Object.const_missing(name)
  @looked_for ||= {}
  key = self.to_s + '~' + name.to_s
  raise "Class not found: #{name}" if @looked_for[key] == key
  return @looked_for[key] if @looked_for[key]
  @looked_for[key] = key
  if self.to_s.include? '::'
    klass = Object
    self.to_s.split('::')[0..-2].each do |klass_string|
      klass = klass.const_get klass_string
    end
    return @looked_for[key] = klass.const_get(name) if klass # klass.is_a?(Class)
  end
  raise "Class not found: #{name}"
end

一些相关问题:

  1. Ruby 是否为类 A::B::C 提供命名空间路径,例如 [:A,:B] 之类的东西?
  2. 如果我在 Ruby Object 类中定义一个类方法,我如何获取调用此方法的子类的名称?
  3. 如何从 Ruby 中的字符串“A::B::C”获取类对象?
于 2010-07-22T23:05:52.497 回答