异构数组有什么意义?
我知道比 Java 更动态的语言,例如 Python 和 Ruby,通常允许您将混合类型的对象放置在数组中,如下所示:
["hello", 120, ["world"]]
我不明白的是为什么您会使用这样的功能。如果我想在 Java 中存储异构数据,我通常会为其创建一个对象。
例如,假设用户
具有int ID
和字符串名称
。虽然我看到在Python/Ruby/PHP中你可以做这样的事情:
[["John Smith", 000], ["Smith John", 001], ...]
这似乎比创建一个带有属性ID
和的类
然后拥有你的数组:User
更不安全/面向对象>name
[<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()
方法),仅使用两者之间共同定义的方法。
I know that more-dynamic-than-Java languages, like Python and Ruby, often allow you to place objects of mixed types in arrays, like so:
["hello", 120, ["world"]]
What I don't understand is why you would ever use a feature like this. If I want to store heterogenous data in Java, I'll usually create an object for it.
For example, say a User
has int ID
and String name
. While I see that in Python/Ruby/PHP you could do something like this:
[["John Smith", 000], ["Smith John", 001], ...]
this seems a bit less safe/OO than creating a class User
with attributes ID
and name
and then having your array:
[<User: name="John Smith", id=000>, <User: name="Smith John", id=001>, ...]
where those <User ...>
things represent User objects.
Is there reason to use the former over the latter in languages that support it? Or is there some bigger reason to use heterogenous arrays?
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.:
class Square extends Shape
class Triangle extends Shape
[new Square(), new Triangle()]
because that is, to the programmer at least, still a homogenous array as you'll be doing the same thing with each shape (e.g., calling the draw()
method), only the methods commonly defined between the two.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
正如 katrielalex 所写: 没有理由不支持异构列表。事实上,禁止它需要静态类型,我们又回到了那个老争论。但我们不要这样做,而是回答“你为什么要使用那个”部分......
说实话,它并没有被使用那么多 - 如果我们在你的最后一个例子中使用异常段落并选择比 Java 或 C# 更自由的“实现相同接口”定义。我的几乎所有可迭代处理代码都期望所有项目都实现某个接口。当然可以,否则它起不了多大作用!
不要误会我的意思,有绝对有效的用例 - 很少有充分的理由编写整个类来包含某些数据(即使您添加了一些可调用对象,函数式编程有时也能解决问题)。不过,字典是更常见的选择,并且 namedtuple 也非常整洁。但它们并不像您想象的那么常见,并且它们是经过深思熟虑和纪律使用的,而不是用于牛仔编码。
(另外,你的“
User
asnested list”示例不是一个好的例子 - 因为内部列表是固定大小的,你最好使用元组,这使得它即使在 Haskell 中也有效(类型为 <代码>[(字符串,整数)]))As katrielalex wrote: There is no reason not to support heterogeneous lists. In fact, disallowing it would require static typing, and we're back to that old debate. But let's refrain from doing so and instead answer the "why would you use that" part...
To be honest, it is not used that much -- if we make use of the exception in your last paragraph and choose a more liberal definition of "implement the same interface" than e.g. Java or C#. Nearly all of my iterable-crunching code expects all items to implement some interface. Of course it does, otheriwise it could do very little to it!
Don't get me wrong, there are absolutely valid use cases - there's rarely a good reason to write a whole class for containing some data (and even if you add some callables, functional programming sometimes comes to the rescue). A dict would be a more common choice though, and namedtuple is very neat as well. But they are less common than you seem to think, and they are used with thought and discipline, not for cowboy coding.
(Also, you "
User
as nested list" example is not a good one - since the inner lists are fixed-sized, you better use tuples and that makes it valid even in Haskell (type would be[(String, Integer)]
))对数组应用 multimethod 可能有意义。您将策略切换为更实用的风格,在这种风格中,您专注于离散的逻辑片段(即多方法)而不是离散的数据片段(即数组对象)。
在您的形状示例中,这使您不必定义和实现
Shape
接口。 (是的,这不是什么大问题,但是如果 shape 是您想要扩展的几个超类之一怎么办?在 Java 中,此时您已经很出色了。)相反,您实现了一个智能draw() multimethod 首先检查参数,然后在对象不可绘制时分派到正确的绘图功能或错误处理。
函数式风格和面向对象风格之间的比较无处不在;这里有几个相关问题应该提供一个良好的开始:函数式编程与面向对象编程< /a> 和 向面向对象程序员解释函数式编程技术人员较少。
Applying a multimethod to the array might make some sense. You switch the strategy to a more functional style in which you focus on a discrete piece of logic (i.e. the multimethod) instead of a discrete piece of data (i.e. the array objects).
In your shapes example, this prevents you from having to define and implement the
Shape
interface. (Yes, it's not a big deal here, but what if shape was one of several superclasses you wanted to extend? In Java, you're SOL at this point.) Instead, you implement a smartdraw()
multimethod that first examines the argument and then dispatches to the proper drawing functionality or error handling if the object isn't drawable.Comparisons between functional and object-oriented styles are all over the place; here are a couple relevant questions that should provide a good start: Functional programming vs Object Oriented programming and Explaining functional programming to object-oriented programmers and less technical people.
是的,有一个非常简单的原因可以解释为什么你可以在 Python 中执行此操作(我假设在 Ruby 中也有同样的原因):
如何检查列表是否是异构的?
repr
发送,因此您也应该能够将它们放在一个列表中。根本没有办法阻止您创建异构列表!
不,我想不出任何。正如您在问题中已经提到的,如果您使用异构数组,您只会让事情变得更加困难。
Yes, there is a very simple reason why you can do this in Python (and i assume the same reason in Ruby):
How would you check that a list is heterogenous?
repr
esented anyways, so you should be able to put them in a list together too.There is simply no way to prevent you from creating a heterogenous list!
No, I can't think of any. As you already mentioned in your question, if you use a heterogenous arrays you're just making things harder than they have to be.
没有理由不支持异构列表。这是出于技术原因的限制,我们不喜欢这些。
并不是所有的事情都需要成为一个类!
在Python中,类基本上是一个增强的字典,无论如何都有一些额外的东西。因此,创建一个类
User
并不一定比字典{"name": ..., "id": ...}
更清晰。There is no reason not to support heterogeneous lists. It's a limitation for technical reasons, and we don't like those.
Not everything needs to be a class!
In Python, a class is basically a souped up dictionary with some extra stuff anyway. So making a class
User
is not necessarily any clearer than a dictionary{"name": ..., "id": ...}
.没有什么可以阻止您在 Java 中使用异构数组。它被认为是较差的编程风格,并且使用适当的 POJO 将比 Java 或任何其他语言中的异构数组更快/更高效,因为“字段”的类型是静态已知的并且可以使用原语。
在Java中你可以
There is nothing to stop you having a heterogeneous array in Java. It is considered poor programming style and using proper POJOs will be faster/more efficient than heterogeneous arrays in Java or any other language as the types of the "fields" are statically known and primitives can be used.
In Java you can
异源列表非常有用。例如,要制作贪吃蛇游戏,我可以有一个如下所示的块列表:
[[x, y, '向下'], [x1, y1, '向下']]
而不是块的类,我可以更快地访问每个元素。
Eterogenous lists are very useful. For instance, to make the game of snake, I can have a list of blocks like this:
[[x, y, 'down'], [x1, y1, 'down']]
instead of a class for the blocks, and I can access faster to every element.
在Lua中,对象和数组是同一件事,所以原因更清楚。假设 Lua 将弱类型发挥到了极致
除此之外,我有一个 Google Map 对象,我需要删除迄今为止在该地图中创建的所有标记。因此,我最终创建了一个标记数组、圆圈数组和地点数组。然后我创建了一个函数来迭代这三个数组并对每个数组调用
.remove()
。然后我意识到我可以只拥有一个非齐次数组并将所有对象插入其中并对该数组迭代一次In Lua an object and an array are the same thing so the reason is more clear. Let's say that Lua takes the weak typing to the extreme
Apart from that, I had a Google Map object and I needed to delete all markers created so far in that map. So I ended up creating an array for
markers
, an array forcircles
and an array forplaces
. Then I made a function to iterate over those three arrays and call.remove()
on each of them. I then realized that I could just have a single non homogeneous array and insert into them all the objects and iterate once over that array这是一个简单的答案:
一切都扩展了 java.lang.Object... 这就足够了。没有理由不拥有 Object[] 并放入您喜欢的任何内容。Object[] 在任何中间件(如持久层)中都非常有用。
Here is a simple answer:
Everything extends java.lang.Object... and that's plenty. There is no reason not to have Object[] and put anything you like in. Object[] are exceptionally useful in any middleware like persistence layer.