获取从给定Class派生的类列表

Ale*_*kin 3 ruby static-analysis ruby-on-rails

我想知道是否有可能获得从给定派生的类列表Class.

我看到,有一个回调Class::inherited,"只要创建当前类的子类就会调用它."这种方法存在两个问题:

  1. 当我不是这个类的生产者时(我说它必须monkeypatch它),我通常不能确保在创建第一个派生类之前应用我的monkeypatch.
  2. 在完美的世界中,我会得到类列表,尽管它们是否已经初始化,而实际上在实例化类时会调用回调.

我理解,RTTI可能不是检索我需要的信息的最佳方式(因为上面的2.).有人会提出另一种方法吗?静态代码分析?任何?

我真的很感激任何想法.说,我在我的目录中拥有所有感兴趣的代码(换句话说,我对我的类感兴趣,仅从一些预定义的类派生,例如ApplicationController在我的Rails应用程序中的s.)

小智 6

如何使用TracePoint?如果以下代码符合您的目的,请告诉我 -

class DerivedClassObserver

  def initialize(classes)
    @classes, @subclasses = classes, {}
  end

  def start
    @trace_point = TracePoint.new(:class) do |tp|
      tp.self.ancestors.map do |ancestor|
        if ancestor != tp.self && @classes.include?(ancestor.name)
          (@subclasses[ancestor.name] ||= []) << tp.self.name
        end
      end
    end

    @trace_point.enable
  end

  def stop
    @trace_point.disable
  end

  def subclasses(class_name)
    @subclasses[class_name]
  end
end
Run Code Online (Sandbox Code Playgroud)

示例用法

observer = DerivedClassObserver.new %w|A AA|
observer.start

# Borrowed example from @Cary
class A       ; end
class AA  < A ; end
class AB  < A ; end
class AC  < A ; end
class AAA < AA; end
class AAB < AA; end
class ABA < AB; end
class ABB < AB; end

observer.stop

puts "A subclasses #{observer.subclasses('A').join(', ')}"
# => A subclasses AA, AB, AC, AAA, AAB, ABA, ABB

puts "AA subclasses #{observer.subclasses('AA').join(', ')}"
# => AA subclasses AAA, AAB
Run Code Online (Sandbox Code Playgroud)

谢谢