我可以轻松地提升Ruby中的类层次结构:
String.ancestors # [String, Enumerable, Comparable, Object, Kernel]
Enumerable.ancestors # [Enumerable]
Comparable.ancestors # [Comparable]
Object.ancestors # [Object, Kernel]
Kernel.ancestors # [Kernel]
Run Code Online (Sandbox Code Playgroud)
有没有办法下降层次结构?我想这样做
Animal.descendants # [Dog, Cat, Human, ...]
Dog.descendants # [Labrador, GreatDane, Airedale, ...]
Enumerable.descendants # [String, Array, ...]
Run Code Online (Sandbox Code Playgroud)
但似乎没有一种descendants方法.
(出现这个问题是因为我想找到Rails应用程序中的所有模型,这些模型来自基类并列出它们;我有一个控制器可以使用任何这样的模型,我希望能够添加新模型无需修改控制器.)
Pet*_*ros 138
这是一个例子:
class Parent
def self.descendants
ObjectSpace.each_object(Class).select { |klass| klass < self }
end
end
class Child < Parent
end
class GrandChild < Child
end
puts Parent.descendants
puts Child.descendants
Run Code Online (Sandbox Code Playgroud)
puts Parent.descendants为您提供:
GrandChild
Child
Run Code Online (Sandbox Code Playgroud)
puts Child.descendants给你:
GrandChild
Run Code Online (Sandbox Code Playgroud)
dgi*_*rez 57
如果使用Rails> = 3,则有两个选项.使用.descendants,如果你想要孩子,班一级以上的深度,或使用.subclasses儿童类的第一级.
例:
class Animal
end
class Mammal < Animal
end
class Dog < Mammal
end
class Fish < Animal
end
Animal.subclasses #=> [Mammal, Fish]
Animal.descendants #=> [Dog, Mammal, Fish]
Run Code Online (Sandbox Code Playgroud)
Jör*_*tag 26
Ruby 1.9(或1.8.7)带有漂亮的链式迭代器:
#!/usr/bin/env ruby1.9
class Class
def descendants
ObjectSpace.each_object(::Class).select {|klass| klass < self }
end
end
Run Code Online (Sandbox Code Playgroud)
Ruby 1.8.7之前的版本:
#!/usr/bin/env ruby
class Class
def descendants
result = []
ObjectSpace.each_object(::Class) {|klass| result << klass if klass < self }
result
end
end
Run Code Online (Sandbox Code Playgroud)
像这样使用它:
#!/usr/bin/env ruby
p Animal.descendants
Run Code Online (Sandbox Code Playgroud)
ape*_*ros 12
或者(更新为ruby 1.9+):
ObjectSpace.each_object(YourRootClass.singleton_class)
Run Code Online (Sandbox Code Playgroud)
Ruby 1.8兼容方式:
ObjectSpace.each_object(class<<YourRootClass;self;end)
Run Code Online (Sandbox Code Playgroud)
请注意,这不适用于模块.此外,YourRootClass将包含在答案中.您可以使用Array# - 或其他方式将其删除.
小智 9
虽然使用ObjectSpace工作,但继承的类方法似乎更适合这里继承的(子类)Ruby文档
Objectspace本质上是一种访问当前使用已分配内存的任何东西和所有内容的方法,因此迭代它的每一个元素以检查它是否是Animal类的子类并不理想.
在下面的代码中,继承的Animal类方法实现了一个回调,它将任何新创建的子类添加到其后代数组中.
class Animal
def self.inherited(subclass)
@descendants = []
@descendants << subclass
end
def self.descendants
puts @descendants
end
end
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
59270 次 |
| 最近记录: |