Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/wix/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在具有相同抽象父类型的对象集合中保持/循环的最佳实践(Julia)_Julia_Software Design - Fatal编程技术网

在具有相同抽象父类型的对象集合中保持/循环的最佳实践(Julia)

在具有相同抽象父类型的对象集合中保持/循环的最佳实践(Julia),julia,software-design,Julia,Software Design,这是一个初学者的问题,我仍然在考虑“面向对象”,所以如果我错过了手册中的答案或者答案很明显,我很抱歉 假设我们有一个抽象类型 abstract type My_Abstract_type end 以及作为该类型子对象的几个具体结构类型: mutable struct Concrete_struct1 <: My_Abstract_type end mutable struct Concrete_struct2 <: My_Abstract_type end ... 但是,正如这里

这是一个初学者的问题,我仍然在考虑“面向对象”,所以如果我错过了手册中的答案或者答案很明显,我很抱歉

假设我们有一个抽象类型

abstract type My_Abstract_type end
以及作为该类型子对象的几个具体结构类型:

mutable struct Concrete_struct1 <: My_Abstract_type end
mutable struct Concrete_struct2 <: My_Abstract_type end
...
但是,正如这里所讨论的,这会带来巨大的性能损失(在我的用例中大约慢25倍)

另一种选择是执行以下操作:

my_array1::Array{Concrete_struct1,1}
my_array2::Array{Concrete_struct2,1}
my_array3::Array{Concrete_struct3,1}
...
processing_fun() = nothing

function processing_fun(x, xs...)
    for my_object in x
        do_something!(my_object)
    end
    processing_fun(xs...)
end
然后

for my_object in my_array1
    do_something!(my_object)
end
for my_object in my_array2
    do_something!(my_object)
end
for my_object in my_array3
    do_something!(my_object)
end

这给了我们想要的性能,但显然是糟糕的软件工程实践,特别是在有大量具体类型的情况下。我们如何在不牺牲性能的情况下干净地存储和循环这些对象?谢谢大家!

如果您的具体类型不超过四种,则只需使用其中的
Union
,如Julia手册所述。对于这种情况,编译器将为您生成一个高效的代码

如果有很多类型,则可以使用数组数组:

a = [my_array1, my_array2, my_array3]
现在你要做什么

foreach(a) do x
    for my_object in x
        do_something!(my_object)
    end
end
现在
a
本身将没有具体的类型,但是对匿名函数的调用应该启用代码专门化。这将有一些开销(对
a
的每个元素进行一次动态调度),但假设每个数组的元素比类型多得多,那么它应该相当快

最后,如果您想完全避免动态调度,而代价是接受巨大的编译成本,您可以编写如下代码:

my_array1::Array{Concrete_struct1,1}
my_array2::Array{Concrete_struct2,1}
my_array3::Array{Concrete_struct3,1}
...
processing_fun() = nothing

function processing_fun(x, xs...)
    for my_object in x
        do_something!(my_object)
    end
    processing_fun(xs...)
end
然后打电话:

processing_fun(a...)
(但如果它是有益的,则必须在您的具体案例中进行基准测试,因为它涉及递归,这也有其成本)