为什么我试图在Ruby中引用嵌套类时出错?

时间:2010-07-22 19:34:06

标签: ruby class namespaces nested nested-class

为什么以下示例中存在错误?

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

2 个答案:

答案 0 :(得分:1)

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

您也可以使用const_missing进行游戏,以便调用ClassA.const_get

否则ClassB不在当前范围内,此时此范围仅为ClassA::ClassEObject。当您首次打开ClassA,然后ClassE时,ClassB的查找首先在ClassA::ClassE中完成,然后在ClassA中找到Object也请查看{{1}}。

答案 1 :(得分: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. Does Ruby provide the namespace path, e.g. something like [:A,:B] for class A::B::C?
  2. If I define a class-method in Ruby Object class, how do I get the name of a child class calling this method?
  3. How do I get class-object from string “A::B::C” in Ruby?