簡體   English   中英

Elixir中模塊的結構重用

[英]Struct reuse for Modules in Elixir

有什么機制可以實現結構重用:定義一個結構,其中包含另一個結構的所有字段以及它自己的一些結構。

我有這些看起來像這樣的結構

defmodule VideoView do
  defstruct name: nil, description: nil, video_link: nil, ...
end

defmodule ImagesView do
  defstruct name: nil, description: nil, images: [], ...
end

defmodule Model3DView do
  defstruct name: nil, description: nil, model: nil, ...
end

其中有7個。 在我的UML中,它們都繼承自View ,它具有namedescription 我希望他們所有人分享這些共同的領域,特別是如果我決定添加或刪除一個公共領域,這可能是當前方法的真正痛苦。

正如其他人所建議的那樣,你應該再考慮一下你是否真的從重新使用結構中獲得了那么多。

如果仍然需要它來減少大量復制,可以使用模塊屬性來初始存儲struct選項。 然后,您可以使用defstruct重新使用它們,並通過函數將它們暴露給其他模塊:

defmodule View do
  @common_fields [name: nil, description: nil]
  def common_fields, do: @common_fields
  defstruct @common_fields
end

如果您不打算單獨使用View ,則可以直接將公共字段放在函數中:

defmodule View do
  def common_fields do
    [name: nil, description: nil]
  end
end

然后,您可以使用其他結構中的公共字段,如下所示:

defmodule VideoView do
  defstruct View.common_fields ++ [video_link: nil, ...]
end

defmodule ImagesView do
  defstruct View.common_fields ++ [images: [], ...]
end

defmodule Model3DView do
  defstruct View.common_fields ++ [model: nil, ...]
end

據我所知,沒有簡單的方法可以做到1.如果你用宏搞亂了,你可能會想出一個。 Elixir中的結構實際上是一個零參數__struct__/0的函數,它返回一個默認值的映射。

您可以將另一個模塊的函數導入到模塊中,如果另一個模塊中的函數被定義為可重寫,則可以使用您自己的定義覆蓋另一個模塊中定義的函數。

use OtherModule

但是你不能導出那些函數,你只能導出模塊中定義的函數。

如果你想繼承Elixir不是你想要使用的語言。 Elixir不是繼承,而是專注於功能的組合和數據的轉換。 從OO世界帶來很多行李只會減慢你的速度。

在這種情況下,如果您需要來自另一個模塊的數據結構,您應該考慮組合而不是繼承。 一種方法是這樣做

defstruct other_module: struct(Other_Module), foo: nil , bar: 1 

在大多數情況下,Elixir是一種基於表達式的語言,您幾乎總是可以為運行時函數調用交換數據值,反之亦然。

  1. 結構重用:

一種。 首先考慮你真的需要重用結構。 聽起來好像你正在考慮將結構作為對象的一種形式。 這並不是說。

如果我們更好地了解您的用例,建議您采取行動將有所幫助。

  1. 功能重用:

一種。 你錯了。 在OO中,通過派生類中的繼承和覆蓋函數實現不同的行為。 在FP中沒有必要,因為您可以簡單地將新功能作為參數傳遞給函數。

請考慮以下示例代碼:

defmodule FReuseExample do
   def func1 do
      IO.puts "func1"
   end

   def func2 do
      IO.puts "func2"
   end

   def my_varying_func(f) do
      f.()
   end
end

然后我會這樣稱呼它:

FReuseExample.my_varying_func(&FReuseExample.func1/0)

或者,如果我需要在func2指定的行為,那么我會這樣做:

FReuseExample.my_varying_func(&FReuseExample.func2/0)

關鍵是我不需要繼承層次結構。 我可以簡單地將我需要的行為作為參數傳遞給函數。 繼承的最初目的是根據所使用的更具體的類型來修改行為。 如果我可以直接傳遞行為,我不再需要繼承來獲取它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM