какой смысл в гетерогенных массивах? - PullRequest
16 голосов
/ 26 декабря 2010

Я знаю, что языки с большей динамичностью, чем Java, такие как Python и Ruby, часто позволяют помещать объекты смешанных типов в массивы, например:

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

Чего я не понимаю, так это того, почему вы бы использовали такую ​​функцию. Если я хочу хранить разнородные данные в Java, я обычно создаю для них объект.

Например, скажем, User имеет int ID и String name. Хотя я вижу, что в Python / Ruby / PHP вы можете сделать что-то вроде этого:

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

это кажется менее безопасным / OO, чем создание класса User с атрибутами ID и name и последующим массивом:

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

где эти <User ...> вещи представляют объекты пользователя.

Есть ли причина использовать первое над последним в языках, которые его поддерживают? Или есть какая-то большая причина использовать гетерогенные массивы?

N.B. Я не говорю о массивах, которые включают разные объекты, которые все реализуют один и тот же интерфейс или наследуют от одного и того же родителя, например ::1010*

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

потому что это, по крайней мере, для программиста по-прежнему однородный массив, поскольку вы будете делать то же самое с каждой формой (например, вызывая метод draw()), только методы, обычно определяемые между ними. 1027 *

Ответы [ 8 ]

4 голосов
/ 26 декабря 2010

Как писал katrielalex: Нет причин не поддерживать гетерогенные списки.На самом деле, запрещение этого потребовало бы статической типизации, и мы вернулись к этим старым дебатам.Но давайте воздержимся от этого и вместо этого ответим на часть «почему вы бы использовали эту» ...

Если честно, она не используется , что много - если мы используемисключение в вашем последнем абзаце и выберите более либеральное определение «реализовать тот же интерфейс», чем, например, Java или C #.Почти весь мой итерируемый код ожидает, что все элементы реализуют некоторый интерфейс.Конечно, это так, иначе это может очень мало с этим поделать!

Не поймите меня неправильно, есть абсолютно правильные варианты использования - редко есть веская причина написать целый класс для хранения некоторых данных (идаже если вы добавите некоторые вызываемые элементы, иногда на помощь приходит функциональное программирование.Однако, dict был бы более распространенным выбором, и namedtuple также очень аккуратен.Но они встречаются реже, чем кажется, и их используют с умом и дисциплиной, а не для ковбойского кодирования.

(Кроме того, вы "User как вложенный список" пример не очень хороший -поскольку внутренние списки имеют фиксированный размер, лучше использовать кортежи, и это делает его действительным даже в Haskell (тип будет [(String, Integer)]))

4 голосов
/ 26 декабря 2010

Применение мультиметода к массиву может иметь некоторый смысл. Вы переключаете стратегию на более функциональный стиль, в котором вы сосредотачиваетесь на отдельном фрагменте логики (то есть на мультиметоде) вместо отдельного фрагмента данных (то есть объектов массива).

В вашем примере фигур это избавляет вас от необходимости определять и реализовывать интерфейс Shape. (Да, здесь нет ничего особенного, но что, если форма была одним из нескольких суперклассов, которые вы хотели бы расширить? В Java вы на этом этапе SOL.) Вместо этого вы реализуете умный draw() мультиметод, который сначала исследует аргумент, а затем отправляет правильные функции рисования или обработки ошибок, если объект не может быть нарисован.

Сравнения между функциональными и объектно-ориентированными стилями повсюду; Вот пара важных вопросов, которые должны обеспечить хорошее начало: Функциональное программирование против объектно-ориентированного программирования и Объяснение функционального программирования для объектно-ориентированных программистов и менее технических специалистов .

3 голосов
/ 26 декабря 2010

Есть ли причина использовать первое над последним в языках, которые его поддерживают?

Да, есть очень простая причина, почему вы можете сделать это в Python (и я предполагаю,по той же причине в Ruby):

Как вы можете проверить, что список неоднороден?

  • Он не может просто сравнивать типы напрямую, потому что в Python есть утка.
  • Если все объекты имеют общий класс типов, Python также не может догадаться об этом. Все в любом случае поддерживает repr esented, поэтому вы также должны иметь возможность объединить их в список.
  • Не имеет смысла превращать списки в только тип , для которого также требуется объявление типа.

Нет никакого способа помешать вам создать гетерогенный список!

Или есть какая-то более серьезная причинаиспользовать гетерогенные массивы?

Нет, я не могу думать ни о каком.Как вы уже упоминали в своем вопросе, если вы используете гетерогенные массивы, вы просто усложняете ситуацию.

2 голосов
/ 26 декабря 2010

Нет причин не поддерживать разнородные списки. Это ограничение по техническим причинам, и нам это не нравится.

Не все должны быть классом!

В Python класс - это, по сути, улучшенный словарь с какими-то дополнительными вещами. Таким образом, создание класса User не обязательно является более понятным, чем словарь {"name": ..., "id": ...}.

1 голос
/ 26 декабря 2010

Ничто не мешает вам иметь гетерогенный массив в Java.Это считается плохим стилем программирования, и использование надлежащих POJO будет быстрее / эффективнее, чем гетерогенные массивы в Java или любом другом языке, поскольку типы «полей» статически известны и могут использоваться примитивы.

В JavaВы можете

Object[][] array = {{"John Smith", 000}, {"Smith John", 001}, ...};
0 голосов
/ 15 мая 2017

В Lua объект и массив - это одно и то же, поэтому причина более ясна. Допустим, Луа доводит слабый тип до крайности

Кроме того, у меня был объект Google Map, и мне нужно было удалить все маркеры, созданные до сих пор на этой карте. В итоге я создал массив для markers, массив для circles и массив для places. Затем я сделал функцию для перебора этих трех массивов и вызова .remove() для каждого из них. Затем я понял, что мог бы просто иметь один неоднородный массив и вставить в них все объекты и выполнить итерацию один раз над этим массивом

0 голосов
/ 26 декабря 2010

Вот простой ответ:

N.B. Я не говорю о массивах, которые включают в себя различные объекты, которые все реализуют один и тот же интерфейс или наследуют от одного и того же родителя, например:

Все расширяет java.lang.Object ... и этого достаточно. , а не , не имеет смысла иметь Object [] и помещать в него все, что вам нравится. Object [] исключительно полезны в любом промежуточном программном обеспечении, например, уровне постоянства.

0 голосов
/ 26 декабря 2010

Этерогенные списки очень полезны.Например, чтобы сделать игру в змею, у меня может быть список таких блоков: [[x, y, 'down'], [x1, y1, 'down']] вместо класса для блоков иЯ могу быстрее получить доступ к каждому элементу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...