在elixir中实现行为的所有模块的列表

时间:2018-12-05 10:55:57

标签: elixir

获取实现行为的所有模块的列表的最短方法是什么?

例如

defmodule X do
  @callback foo()
end

defmodule A do
  @behaviour X
  def foo() do
    "hello"
  end
end

defmodule B do
  @behaviour X
  def foo() do
    "world"
  end
end

我想以[A,B]的身份获得清单。我尝试加载所有模块,然后使用键属性behaviour进行过滤,但我认为它会非常慢。还有其他更好的方法吗?

2 个答案:

答案 0 :(得分:5)

没有,没有更好的方法。行为不会以任何方式建立索引,因为它们是一种编译时功能,用于检查是否已定义所有必需的回调函数。所以像这样的东西就够了:

for {module, _} <- :code.all_loaded(),
    X in (module.module_info(:attributes)[:behaviour] || []) do
        module
end

答案 1 :(得分:0)

继续执行提供的@legoscia解决方案。 在某些情况下,每个模块可能要实现1个以上的行为,例如:

for {module, _} <- :code.all_loaded(),
    __MODULE__ in (module.module_info(:attributes)
                   |> Keyword.get_values(:behaviour)
                   |> List.flatten()) do
  module
end

应作为关键字列表使用重复的关键字,并且直接访问它们不会返回期望的结果。

感谢@legoscia!