Подтвердить что ты не робот

Какова точка гетерогенных массивов?

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

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

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

Например, скажем, a 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. Я не говорю о массивах, которые включают в себя разные объекты, которые реализуют один и тот же интерфейс или наследуют от одного и того же родителя, например:

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

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

4b9b3361

Ответ 1

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

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

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

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

Ответ 2

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

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

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

Ответ 3

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

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

Как вы проверите, что список является гетерогенным?

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

Просто невозможно предотвратить создание гетерогенного списка!

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

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

Ответ 4

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

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

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

Ответ 5

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

В Java вы можете

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

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