我正在考虑编写类似于NamedArrays和Images中定义的类型。让我们说我只是想要一个带有一段元数据的数组,比如一个用户友好的名字,当我将数组写入磁盘时,我将在文件的顶部写入。 (这个细节不相关;我只是在设计一个例子。)
所以我可能会这样做
type MyNamedArray
data::Array
name::ASCIIString
end
function mywrite(f,x::MyNamedArray)
write(f,x.name)
write(f,x.data)
end
或其他东西,没有其他行为需要与基本阵列行为不同。
在我脑海中,它显而易见"我只希望在Arrays上运行的每个现有函数都在这种类型的data
字段上运行。用其他语言,例如Java我可能只是将子类化为Array并将name
作为实例字段添加到子类中,这将自动保持与所有现有Array操作的兼容性。但在朱莉娅,如果我尝试上述解决方案,我现在需要定义更多功能,例如作为@TimHoly和' davidavdav'已完成链接包。
当然我知道被迫手工写出这些功能对于实现你没有想过的事情很有用。例如。在上面给出的示例MyNamedArray
中,我可以指出我还没有定义x::MyNamedArray * y::MyNamedArray
的名称。但是,如果我不关心这一点,并希望代码“只是起作用”,那该怎么办?没有那么多样板? (参见例如循环符号以推送新的方法定义in NamedArrays并手动写出一百行定义in Images。这些定义中的绝大多数都是样板/明显的#34;定义。)
具体来说,继续我引用的示例,对于MyNamedArray
,默认值x*y
不再是MyNamedArray
,即因为每个函数都默认为"继承& #34;在底层数据上应用相同功能的行为,我们可以忘记所有预先存在的函数的元数据。
注意,我发现Tomas Lycken的回答here很有见地,问题和答案here也是如此。
我能想到的最好的合成是#34;你只需要把它搞砸并写出函数,或者写一个为你做这个的宏。"如果是这样的话,那就这样吧;我只是想知道我是否错过了更好的选择,特别是设计解决方案以使其更具朱利安并避免使用样板的更好方法。
答案 0 :(得分:6)
您可以通过简单地继承AbstractArray
:http://docs.julialang.org/en/latest/manual/interfaces/#abstract-arrays来完成大部分工作。事实上,你可以做一个更好的子类DenseArray
,这还需要定义一个stride
(可能是pointer
)函数......允许你的自定义数组使用BLAS。这只是你需要定义的一些方法。它不是100%,因为许多作者仍然倾向于过度限制方法,只有当他们能够轻易接受所有Array
时才接受AbstractArrays
。这种情况在过去两年里得到了明显的改善,并且还在不断改进。
通常,我发现在这里非常有用的模式是根据抽象超类型定义接口,并尽可能地放松方法签名。如果不需要调度限制,您可以允许任何类型,只需依靠鸭子打字。如果你只是在告诉Julia它应该如何嘲笑或者依赖于它的内部实现时,只将发送限制到特定的叶子类型,那么你的工作就变得更具可扩展性和可重用性。