直接在Elixir中使用调用模块函数defdelegate和def之间有什么区别

kov*_*ack 7 module function elixir

我有一个主要用作命名空间的模块.我们称之为Bla.还有其他子模块,它们具有对该子模块具有特定功能的方法.

但是,我想有两个选择:

1)导入主模块Bla并直接使用子模块中的所有函数(不单独写入多个导入)

2)仅导入特定子模块,例如Bla.Subbla仅使用此模块中的函数而不从其他子模块导入函数

这就是我所拥有的:

defmodule Bla do
  defdelegate bla_func(text), to: Bla.Subbla
  defdelegate bla_func(text, opts), to: Bla.Subbla
end

defmodule Bla do
  def bla_func(text), do: Bla.Subbla.bla_func(text)
  def bla_func(text, opts), do: Bla.Subbla.bla_func(text, opts)
end
Run Code Online (Sandbox Code Playgroud)

这样做的正确方法是什么?我有两个选择,但不知道,也许,还有更好的选择.这两个选项是否相同?哪个更好?性能有什么不同吗?

Kha*_*din 6

我能想到的一些差异:

  1. 当你使用defdelegate你的意图时非常清楚,你只是将方法委托给另一个模块中的另一个方法.而这只是一个愚蠢的货运代理人.
  2. 随着defdelegate你无法改变arguments,无论是顺序,添加或删除参数.所以,如果您真正想要的是转发方法调用,defdelgate因为没有更多的空间搞砸了.
  3. 在某些情况下defdelegate,不是一个选项,因为您需要向转发功能添加更多数据,在这种情况下您实际上没有选项.

因此,底线是:如果可能的话总是使用defdelegate,你将避免使用它的一些类错误.例如下面:

defmodule Greet do
  def greet(name, greeting) do
    IO.puts "#{greeting} #{name}"
  end
end

defmodule DelegatedGreet do
  defdelegate greet(name, greeting), to: Greet
end

defmodule BuggyGreet do
  # scope for bugs like these
  def greet(name, greeting), do: Greet.greet(greeting, name)
end
Run Code Online (Sandbox Code Playgroud)