关于java:异构数组有什么意义?

what is the point of heterogenous arrays?

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

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

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

例如,假设User具有int IDString name。虽然我在Python / Ruby / PHP中看到你可以这样做:

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

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

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

其中事物代表用户对象。

是否有理由在支持它的语言中使用前者而不是后者?或者是否有更大的理由使用异构数组?

注:我不是在讨论包含所有实现相同接口或从同一父接口继承的不同对象的数组,例如:

1
2
3
class Square extends Shape
class Triangle extends Shape
[new Square(), new Triangle()]

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


正如katrielalex写道:没有理由不支持异构列表。事实上,不允许它需要静态打字,我们回到那个古老的辩论。但是,我们不要这样做,而是回答"为什么要使用那个"部分......

说实话,它没有那么多使用 - 如果我们在你的最后一段中使用异常并选择一个更自由的定义"实现相同的接口"而不是例如Java或C#。几乎所有我的可迭代代码都希望所有项都能实现一些接口。当然它确实如此,否则它可以做很少的事情!

不要误会我的意思,有绝对有效的用例 - 很少有理由写一个完整的类来包含一些数据(即使你添加一些callables,函数式编程有时也会拯救)。虽然dict是一个更常见的选择,而且namedtuple也非常简洁。但它们并不像你想象的那么普遍,它们被用于思想和纪律,而不是用于牛仔编码。

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


将多方法应用于数组可能有一定道理。您可以将策略切换到更具功能性的样式,在该样式中您可以专注于离散的逻辑片段(即多方法),而不是离散的数据片段(即数组对象)。

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

功能和面向对象风格之间的比较到处都是;这里有几个相关的问题应该提供一个良好的开端:功能编程与面向对象的编程和向面向对象的程序员和技术人员解释函数式编程。


Is there reason to use the former over
the latter in languages that support
it?

是的,有一个非常简单的原因可以让你在Python中做到这一点(我在Ruby中假设相同的原因):

你如何检查列表是异质的?

  • 它不能直接比较类型,因为Python有鸭子打字。
  • 如果所有对象都有一些常见的类型类,Python也无法猜测。无论如何,一切都支持repr,所以你也应该能够将它们放在一个列表中。
  • 将列表转换为需要类型声明的唯一类型也没有任何意义。

根本没有办法阻止你创建一个异类列表!

Or is there some bigger reason to use
heterogenous arrays?

不,我想不出任何。正如您在问题中已经提到的那样,如果您使用异构数组,那么您只是将事情变得更加艰难。


没有理由不支持异构列表。这是技术原因的限制,我们不喜欢这些。

并非一切都需要成为一个班级!

在Python中,一个类基本上是一个带有一些额外内容的加强字典。因此,使类不一定比字典{"name": ...,"id": ...}更清晰。


没有什么可以阻止你在Java中使用异构数组。它被认为是糟糕的编程风格,并且使用适当的POJO将比Java或任何其他语言中的异构数组更快/更有效,因为"字段"的类型是静态已知的并且可以使用原语。

在Java中你可以

1
Object[][] array = {{"John Smith", 000}, {"Smith John", 001}, ...};

在Lua中,对象和数组是相同的,所以原因更清楚。让我们说Lua将弱打字变为极端

除此之外,我有一个谷歌地图对象,我需要删除到目前为止在该地图中创建的所有标记。所以我最终为markers创建了一个数组,一个circles的数组和一个places的数组。然后我创建了一个迭代这三个数组的函数,并在每个数组上调用.remove()。然后我意识到我可以只有一个非同类数组并将所有对象插入其中并在该数组上迭代一次


Eterogenous列表非常有用。例如,为了制作蛇游戏,我可以有一个像这样的块列表:
[[x,y,'down'],[x1,y1,'down']]
而不是块的类,我可以更快地访问每个元素。


这是一个简单的答案:

N.B. I am not talking about arrays that include different objects that
all implement the same interface or inherit from the same parent, e.g.:

一切都扩展了java.lang.Object ......而且这很多。没有理由不使用Object []并放置任何你喜欢的东西.Object []在持久层等任何中间件中都非常有用。