模块属性Elixir

时间:2014-10-06 03:55:52

标签: erlang elixir

我是Elixir / Erlang编程的新手。

如何为Elixir模块实现模块属性,因此模块的用户可以在模块构造函数中设置。

例如,

defmodule Config do
    some_property: nil
    other_property: nil

    def constructor(one, two) do
        some_property = one
        other_property = two
    end

    def get_property_one do 
        some_property
    end
end

谢谢

2 个答案:

答案 0 :(得分:6)

Elixir模块不是类,它们内部定义的变量不是属性,因此没有构造函数和析构函数之类的东西。 Elixir基于Erlang,所以首先,我会推荐一些关于Erlang和面向对象编程的阅读:

这应该为您提供基本的想法,为什么不支持具有getter和setter的对象。使对象具有状态的最接近的事情是具有状态的server。所以在服务器循环中,你可以这样做:

def loop(state) do
  newstate = receive do
    { :get_property_one, pid } ->
      pick_the_property_from_state_and_send_to_pid(state, pid)
      state
    { :set_property_one } ->
      set_property_one_and_return_new_state(state)
  end
  loop(newstate)
end

使用构造函数生成具有初始状态的新服务器即将创建新对象。发送:get_property_one就像getter一样,但是异步(你可以在等待回复之前做一些其他事情)。发送:set_property_one并不等待回复,因此它不会阻止。

这可能看起来很麻烦,但它解决了几个问题:

  • 你不会在Erlang中有读者,作家问题,因为所有请求都是逐一处理的
  • 如果你的getter和setter需要一些复杂的操作,它们可以异步完成(不会阻塞调用进程)

这种模式很常见,有behaviour called gen_server,它消除了大部分循环的样板。如果您仍然认为,要编写的样板太多,您可以阅读my article about it(这个是在Erlang中)

答案 1 :(得分:1)

我认为你最接近OO的是

defmodule Config do

  defstruct [
    some_property: nil,
    other_property: nil
  ]

  def new(one, two) do
    %Config{
      some_property: one,
      other_property: two
    }
  end

  #Getter
  def property_one(this) do 
    this.some_property
  end

  #Setter
  def property_one(this, value) do 
    %{this | some_property: value}
  end
end

你必须像这样使用它

conf = Config.new("a", 2)
Config.property_one(conf) # == "a"
conf = Config.property_one(conf, "b") # == %Config{some_property: "b", other_property: 2}

如您所见,它们只是提取/集成一些信息到/结构中的函数。我喜欢C#和Dart中的getter和setter,但是在FP世界中它们只是函数,不多也不少。