有什么机制可以实现结构重用:定义一个结构,其中包含另一个结构的所有字段以及它自己的一些结构。
我有这些看起来像这样的结构
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
,name
和description
。我希望他们所有人都能分享这些共同的领域,特别是如果我决定添加或删除一个公共领域,这可能是当前方法的真正痛苦。
答案 0 :(得分:10)
正如其他人所建议的那样,你应该再考虑一下你是否真的从重新使用结构中获得了那么多。
如果仍然需要它来减少大量复制,可以使用模块属性来初始存储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 :(得分:2)
据我所知,没有简单明了的方法1.如果你对宏进行了充分的处理,你可能会想出一个。 Elixir中的结构实际上是一个零参数__struct__/0
的函数,它返回一个映射
使用默认值。
您可以将另一个模块的功能导入到您的模块中,并且可以使用您自己的定义覆盖另一个模块中定义的功能,如果 其他模块中的函数定义为可重写。
use OtherModule
但是你不能导出那些函数,你只能导出定义的函数 在模块中。
如果你想继承Elixir不是你想要使用的语言。 Elixir不是继承,而是专注于功能的组合和数据的转换。从OO世界带来很多行李只会让你失望。
在这种情况下,如果您需要来自另一个模块的数据结构,您应该考虑组合而不是继承。一种方法是
defstruct other_module: struct(Other_Module), foo: nil , bar: 1
在大多数情况下,Elixir是一种基于表达式的语言,您几乎总能为运行时函数调用交换数据值,反之亦然。
答案 2 :(得分: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)
重点是我不需要继承层次结构。我可以简单地将我需要的行为作为参数传递给函数。继承的最初目的是根据所使用的更具体的类型来修改行为。如果我可以直接传递行为,我不再需要继承来获取它。