我知道比Java和Ruby更动态的Java语言通常允许您将混合类型的对象放在数组中,如下所示:
["hello", 120, ["world"]]
我不明白为什么你会使用这样的功能。如果我想在Java中存储异构数据,我通常会为它创建一个对象。
例如,假设User
有int ID
和String name
。虽然我在Python / Ruby / PHP中看到你可以这样做:
[["John Smith", 000], ["Smith John", 001], ...]
这似乎比创建具有属性User
和ID
的类name
然后拥有您的数组更安全/ OO:
[<User: name="John Smith", id=000>, <User: name="Smith John", id=001>, ...]
其中<User ...>
个事物代表用户对象。
是否有理由在支持它的语言中使用前者而不是后者?或者是否有更大的理由使用异构数组?
N.B。我不是在谈论包含所有实现相同接口或从同一父节点继承的不同对象的数组,例如:
class Square extends Shape
class Triangle extends Shape
[new Square(), new Triangle()]
因为至少对于程序员来说,仍然是一个同质数组,因为你将对每个形状做同样的事情(例如,调用draw()
方法),只有两者之间通常定义的方法
答案 0 :(得分:4)
将multimethod应用于数组可能会有所帮助。您可以将策略切换到更具功能性的样式,在该样式中您可以专注于离散的逻辑片段(即多方法),而不是离散的数据片段(即数组对象)。
在形状示例中,这可以防止您必须定义和实现Shape
接口。 (是的,这不是什么大问题,但如果形状是你想要扩展的几个超类之一呢?在Java中,你现在就是SOL。)相反,你实现了一个智能的draw()
多方法。检查参数,然后如果对象不可绘制,则调度到正确的绘图功能或错误处理。
功能和面向对象风格之间的比较到处都是;以下是一些应该提供良好开端的相关问题:Functional programming vs Object Oriented programming和Explaining functional programming to object-oriented programmers and less technical people。
答案 1 :(得分:4)
正如katrielalex所写:没有理由不支持异构列表。事实上,不允许它需要静态打字,我们回到那个古老的辩论。但是,我们不要这样做,而是回答“为什么要使用那个”部分......
老实说,如果我们在你的最后一段中使用了异常并且选择了比“实现相同的接口”更自由的定义,那么 就不会那么多了。 Java或C#。几乎所有我的可迭代代码都希望所有项都能实现一些接口。当然它确实如此,否则它可以做很少的事情!
不要误解我的意思,有绝对有效的用例 - 很少有充分的理由来编写一个包含一些数据的整个类(即使你添加了一些callables,函数式编程有时也可以解决)。虽然dict是一个更常见的选择,namedtuple也非常简洁。但它们并不像你想象的那么普遍,它们被用于思想和纪律,而不是用于牛仔编码。
(另外,你“User
作为嵌套列表”示例不是一个好例子 - 因为内部列表是固定大小的,你最好使用元组,即使在Haskell中它也有效(类型将是{ {1}}))
答案 2 :(得分:3)
是否有理由使用前者 后者用支持的语言 它?
是的,有一个非常简单的原因可以让你在Python中做到这一点(我在Ruby中假设同样的原因):
repr
提出,所以你也应该能够将它们放在一个列表中。或者有更大的理由可以使用 异构数组?
不,我想不出来。正如您在问题中已经提到的那样,如果您使用异构数组,那么您只是将事情变得更加艰难。
答案 3 :(得分:2)
没有理由不支持异构列表。这是技术原因的限制,我们不喜欢这些。
并非一切都需要成为一个阶级!
在Python中,一个类基本上是一个带有一些额外内容的加强字典。因此,创建一个类User
并不一定比字典{"name": ..., "id": ...}
更清晰。
答案 4 :(得分:1)
没有什么可以阻止你在Java中使用异构数组。它被认为是糟糕的编程风格,并且使用适当的POJO将比Java或任何其他语言中的异构数组更快/更有效,因为“字段”的类型是静态已知的并且可以使用原语。
在Java中你可以
Object[][] array = {{"John Smith", 000}, {"Smith John", 001}, ...};
答案 5 :(得分:0)
Eterogenous列表非常有用。例如,为了制作蛇游戏,我可以有一个像这样的块列表: [[x,y,'down'],[x1,y1,'down']] 而不是块的类,我可以更快地访问每个元素。
答案 6 :(得分:0)
在Lua中,对象和数组是相同的,所以原因更清楚。让我们说Lua将弱打字变为极端
除此之外,我有一个谷歌地图对象,我需要删除目前在该地图中创建的所有标记。所以我最终为markers
创建了一个数组,一个circles
数组和一个places
数组。然后我创建了一个迭代这三个数组的函数,并在每个数组上调用.remove()
。然后我意识到我可以只有一个非同构数组并将所有对象插入其中并在该数组上迭代一次
答案 7 :(得分:-1)
这是一个简单的答案:
N.B。我不是在谈论包含不同对象的数组 所有都实现相同的接口或从同一父节点继承,例如:
一切都扩展了java.lang.Object ......而且这很多。没有理由不拥有Object []并放入您喜欢的任何内容.Object []在持久层等任何中间件中都非常有用。