use*_*152 8 ruby ruby-on-rails
如果我有4个具有以下层次结构的类:
class MainClass < ActiveRecord::Base
...
end
class SubClassA < MainClass
...
end
class SubClassB < MainClass
...
end
class SubClassC < MainClass
...
end
Run Code Online (Sandbox Code Playgroud)
如何在不经过并创建其他每个类的实例的情况下获取MainClass的子类列表?
在一个新的IRB会议中,我可以进去说
irb(main)> MainClass.descendants
=> []
Run Code Online (Sandbox Code Playgroud)
但是,如果我经历并创建每个子类的实例,我将看到以下内容
irb(main)> SubClassA.new
=> #<SubClassA ...>
irb(main)> SubClassB.new
=> #<SubClassB ...>
irb(main)> SubClassC.new
=> #<SubClassC ...>
irb(main)> MainClass.descendants
=> [SubClassA(...), SubClassB(...), SubClassC(...)]
Run Code Online (Sandbox Code Playgroud)
我基本上是在寻找一种方法来提供所有子类的方法,以便将来当我想添加SubClassD,SubClassE等时,我不必担心每个人都会在代码中实例化,然后用户才能看到它们.
这是一个开发模式的假象,只在第一次引用时加载类:那些文件还没有被解释器读取 - 就ruby而言,这些类真的还不存在
解决方法是放置
require_dependency "subclass_a"
require_dependency "subclass_b"
....
Run Code Online (Sandbox Code Playgroud)
在底层主类的文件(在类定义之外)
有几种方法可以实现这一目标.通过使用诸如descendants_tracker之类的gem :
class MainClass < ActiveRecord::Base
extend DescendantsTracker
end
class SubClassA < MainClass
end
...
MainClass.descendants # => [SubClassA]
Run Code Online (Sandbox Code Playgroud)
或者你可以在你的父类中创建一个自定义的,如下所示:
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
Run Code Online (Sandbox Code Playgroud)
您还可以检查依赖关系的级别.例如,如果你想要一个MainClass的直接子数组,你可以使用.subclasses类方法
MainClass.subclasses # => [SubClassA, SubClassB,...]
Run Code Online (Sandbox Code Playgroud)
现在,如果您想要多个级别的子类使用.descendants.你可以在这里找到一个例子
| 归档时间: |
|
| 查看次数: |
2595 次 |
| 最近记录: |