如何在不首先在Ruby中实例化的情况下获取所有子类的列表

时间:2016-01-15 18:37:25

标签: ruby-on-rails ruby

如果我有4个具有以下层次结构的类:

class MainClass < ActiveRecord::Base
  ...
end

class SubClassA < MainClass
  ...
end

class SubClassB < MainClass
  ...
end

class SubClassC < MainClass
  ...
end

如何在不经过并创建其他每个类的实例的情况下获取MainClass的子类列表?

在新的IRB会议中,我可以进去说

irb(main)> MainClass.descendants
=> []

但是,如果我经历并创建每个子类的实例,我将看到以下

irb(main)> SubClassA.new
=> #<SubClassA ...>
irb(main)> SubClassB.new
=> #<SubClassB ...>
irb(main)> SubClassC.new
=> #<SubClassC ...>
irb(main)> MainClass.descendants
=> [SubClassA(...), SubClassB(...), SubClassC(...)]

我基本上都在寻找一种方法来编程提供所有子类,以便将来当我想添加SubClassD,SubClassE等时,我不必担心每个人都在用户之前的代码中实例化可以看到他们。

3 个答案:

答案 0 :(得分:9)

这是一个开发模式的假象,只在第一次引用时加载类:那些文件还没有被解释器读取 - 就ruby而言,这些类真的还不存在

解决方法是放

/** Servlet implementation class FetchTest */
@WebServlet( urlPatterns = {"/users", "/Users/"})
public class Users extends HttpServlet
{
    /** @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response) */
    protected void doGet( HttpServletRequest request , HttpServletResponse response ) throws ServletException , IOException
    {
        m_showUsers( response);
    }

    /** @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response) */
    protected void doPost( HttpServletRequest request , HttpServletResponse response ) throws ServletException , IOException
    {
        m_updateUser(request , response);
    }
    @Override
    protected void doDelete( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException
    {
        m_deleteUser(req , resp);
    }
    @Override
    protected void doPut( HttpServletRequest req , HttpServletResponse resp ) throws ServletException , IOException
    {
        m_insertUser(req , resp);
    }

在主要类的文件底部(类定义之外)

答案 1 :(得分:8)

有几种方法可以实现这一目标。通过使用诸如descendants_tracker

之类的宝石
class MainClass < ActiveRecord::Base
  extend DescendantsTracker
end

class SubClassA < MainClass 
end

...

MainClass.descendants # => [SubClassA]

或者您可以在父类中创建自定义的内容,例如this

class  MainClass < ActiveRecord::Base
  def self.descendants
    ObjectSpace.each_object(Class).select { |klass| klass < self }
  end
end

class SubClassA < MainClass 
end

class SubClassB  < MainClass 
end

puts MainClass.descendants 

#=> SubClassA
    SubClassB  

您还可以检查依赖关系的级别。如果你想要一个MainClass直接子节点的数组,例如你可以使用.subclasses类方法

MainClass.subclasses  # => [SubClassA, SubClassB,...]

现在,如果您想要多个级别的子类,请使用.descendants。您可以找到示例here

答案 2 :(得分:0)

您可以使用ObjectSpace#each_object来编制 back = re.compile("'\\\\'") print back.findall(line) 个孩子的列表:

假设:

MainClass

class MainClass ; end class SubClassA < MainClass; end class SubClassB < MainClass; end class SubClassC < SubClassB; end 可能是一个子类的事实是无关紧要的。

MainClass