【问题标题】:How to modify existing module behaviour in Elixir?如何修改 Elixir 中现有的模块行为?
【发布时间】:2016-09-24 08:32:46
【问题描述】:

是否可以在没有__using__/1 功能的模块中添加新功能?

例如,我想在 Phoenix.Tracker 中添加get_meta_by_key 函数。如果我和

defmodule MyApp.MyTracker do
  use Phoenix.Tracker

  def get_meta_by_key(..., topic, key)
    ...
  end

  handle_call(:get_meta_by_key, ..., state)
    ...
  end
end

然后我得到** (UndefinedFunctionError) undefined function Phoenix.Tracker.__using__/1

我想在内存中分发键值存储以保留一些临时值,但不知道如何在不重新发明轮子和不使用 Phoenix.Tracker.list 函数的情况下做到这一点,然后处理完整列表调用方。

我是 Elixir/Phoenix 的新手,所以如果我的问题很愚蠢,请原谅。

【问题讨论】:

  • 或许你想看看这个问答:stackoverflow.com/questions/35302208/…
  • @OnorioCatenacci,非常感谢这一点!但是我找不到正常的方法来实现很少的添加(实际上是几行代码)而不分叉现有的模块(然后在支持和升级它时遇到很大的麻烦)。经过多年的 OOP 之后,切换到函数式的方式并不容易,但此刻我什至无法想象如何以简单有效的方式实现我的需求。
  • @OnorioCatenacci 当然,我可以制作一个“更高级别”的函数,它可以处理从 Tracker 返回的完整列表,但我认为这不是一种有效的方法:如果我理解正确,这将在每次通话时复制整个列表。
  • 我不会假设它会在每次通话时复制整个列表。事实上,我会假设完全相反。我假设指向列表的指针每次都会以静默方式传递。但这就是我。如果您要求使用“函数式”方式来扩展行为,则高阶函数是执行此操作的常规方式。
  • 顺便说一下,我不会根据假设更改代码。我会首先尝试获取经验数据,然后如果我有经验证据,那么我会更改我的代码以处理出现的任何问题。猜测性能是过早的优化。

标签: elixir phoenix-framework


【解决方案1】:

您可以使用带有using 的宏编写自己的宏。这是与元编程相关的,我强烈建议您查看 Metaprogramming Elixir 书。您还需要使用quoteunquote

您也可以参考this

【讨论】:

  • 萨沙,非常感谢您的回答!如果我不够清楚,请原谅。 Phoenix.Tracker - 它已经存在的模块。我不想破解它以保持正常的升级方式,否则我只会复制它并破解。我想扩展这个模块,但不知道怎么做。还是我误解了你的想法?那请解释一下。谢谢!
  • 如果没有 using 宏,我不记得有任何方法可以扩展它。我认为可能有用的是拥有另一个模块(我们称之为TrackerExtender),您可以在其中从Phoenix.Tracker 导入TrackerExtender 中的使用宏中的函数。这样,当您的 MyTracker 模块调用使用 TrackerExtender 时,他将收到来自 Phoenix.Tracker 的函数以及 TrackerExtender 中新定义的函数。但我不完全确定这是否有效或是否符合您的需求。
  • 萨沙,感谢您的宝贵时间!我无法让您的解决方案发挥作用,但不能确定这不是因为我的灵丹妙药技能不佳。
猜你喜欢
  • 1970-01-01
  • 2017-10-31
  • 1970-01-01
  • 1970-01-01
  • 2019-11-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多