异构阵列的意义何在?

2022-09-03 07:17:39

我知道比Java更动态的语言,如Python和Ruby,通常允许你将混合类型的对象放在数组中,如下所示:

["hello", 120, ["world"]]

我不明白的是,为什么你会使用这样的功能。如果我想在Java中存储异构数据,我通常会为它创建一个对象。

例如,假设 a has 和 .虽然我看到在Python / Ruby / PHP中你可以做这样的事情:Userint IDString name

[["John Smith", 000], ["Smith John", 001], ...]

这似乎比创建一个带有属性的类然后拥有数组更安全/ OO:UserIDname

[<User: name="John Smith", id=000>, <User: name="Smith John", id=001>, ...]

其中,这些内容表示用户对象。<User ...>

在支持前者的语言中,是否有理由使用前者而不是后者?还是有更大的理由使用异构阵列?

注意:贝我不是在谈论包含不同对象的数组,这些对象都实现了相同的接口或从同一父级继承,例如:

class Square extends Shape
class Triangle extends Shape
[new Square(), new Triangle()]

因为至少对于程序员来说,这仍然是一个同构数组,因为你将对每个形状做同样的事情(例如,调用方法),只有两者之间通常定义的方法。draw()


答案 1

正如katrielalex所写:没有理由不支持异构列表。事实上,禁止它需要静态类型,我们又回到了那个古老的争论。但是,让我们不要这样做,而是回答“你为什么要使用它”部分......

老实说,它并没有被使用那么多 - 如果我们利用你最后一段中的例外,并选择一个更自由的“实现相同的接口”的定义,而不是例如Java或C#。几乎所有的可迭代处理代码都希望所有项目都实现某个接口。当然可以,但除此之外,它可能对它无能为力!

不要误会我的意思,有绝对有效的用例 - 很少有充分的理由编写包含某些数据的整个类(即使您添加了一些可调用的,函数式编程有时也会来拯救)。不过,字典将是一个更常见的选择,命名图勒也非常整洁。但它们并不像你想象的那么常见,它们被用于思想和纪律,而不是用于牛仔编码。

(另外,你“作为嵌套列表”的例子不是一个好的例子 - 因为内部列表是固定大小的,你最好使用元组,这使得它即使在Haskell中也是有效的(类型将是User[(String, Integer)]))


答案 2

对数组应用多方法可能有些意义。您将策略切换到一种功能更强大的样式,在这种风格中,您专注于离散的逻辑片段(即多方法)而不是离散的数据片段(即数组对象)。

在形状示例中,这可以避免您定义和实现接口。(是的,这没什么大不了的,但是如果形状是您想要扩展的几个超类之一呢?在Java中,你现在是SOL。相反,您可以实现一个智能多方法,该方法首先检查参数,然后在对象不可绘制时调度到正确的绘制功能或错误处理。Shapedraw()

函数式和面向对象样式之间的比较无处不在;这里有一些相关的问题应该提供一个良好的开端:函数式编程与面向对象编程并向面向对象程序员和较少的技术人员解释函数式编程