Зачем возвращать объект вместо массива?

84

Я много работаю в WordPress и заметил, что гораздо больше функций возвращают объекты, чем массивы. Результаты базы данных возвращаются как объекты, если вы специально не запрашиваете массив. Ошибки возвращаются как объекты. За пределами WordPress большинство API предоставляют объект вместо массива.

У меня вопрос, почему они используют объекты вместо массивов? По большей части это не имеет большого значения, но в некоторых случаях мне сложнее не только обработать объекты, но и осмыслить их. Есть ли причина производительности для использования объекта?

Я программист-самоучка на PHP. У меня есть степень гуманитарных наук. Так что простите меня, если я упускаю фундаментальный аспект информатики. ;)

Деннис
источник
5
Мне любопытно это в отношении недостатков объектов, таких как невозможность использования count()или array_*()функций на них (по крайней мере, в отношении хранения / возврата данных ключа => значения). Кажется, никто об этом не упоминает, или я что-то упускаю?
Уэсли Мерч
8
Объекты можно сделать счетными и повторяемыми, реализовав интерфейсы Countable или Iterator. Также посетите php.net/manual/en/book.spl.php .
simshaun
Если у вас установлен SPL и вы реализуете интерфейс, учитываемый для вашего объектного класса, вы можете вызывать count()объект.
Никто не уезжает из SE
2
Во многих случаях массив даже не имеет смысла, потому что вы не возвращаете коллекцию объектов или коллекцию, которую нелегко эмулировать с помощью массивов. Когда у вас просто есть последовательность других значений и нет связанной дополнительной семантики, тогда, ради бога, верните массив - но вы обнаружите, что это редко.
8
@delnan и другие: обратите внимание, что @Dennis говорит об ассоциативных массивах (также известных как словари, карты), а не об обычных (целочисленных) массивах. Это основная функция PHP, и они служат более или менее той же цели, что и динамические классы ( stdClass). Я не уверен, что у этого вопроса есть ответ, кроме «Потому что программисты, которые работают в основном с ООП, предпочитают семантику использования объектов»
BlueRaja - Дэнни Пфлугофт

Ответы:

63

Вот причины, по которым я предпочитаю объекты в целом:

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

Здесь есть что почитать:

Саша Галлея
источник
3
первая ссылка вроде не годится? Я имею в виду, что это работает, но требует другой работы
Geo,
24

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

Давайте рассмотрим несколько примеров.

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

Подумайте о методе API, который возвращает список сообщений WordPress. У всех этих сообщений есть авторы, у авторов есть имена, адрес электронной почты, возможно, даже профили с их биографиями.

Если вы возвращаете все сообщения в массиве, вам либо придется ограничиться возвратом массива идентификаторов сообщений:

[233, 41, 204, 111]

или возвращая массивный массив, который выглядит примерно так:

[ title: 'somePost', body: 'blah blah', 'author': ['name': 'billy', 'email': 'bill@bill.com', 'profile': ['interests': ['interest1', 'interest2', ...], 'bio': 'info...']] ]
[id: '2', .....]]

Первый случай возврата списка идентификаторов не очень полезен для вас, потому что тогда вам нужно сделать вызов API для каждого идентификатора, чтобы получить некоторую информацию об этом сообщении.

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

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

  • Массивы предоставляют больше данных и возможностей, чем предполагалось

Вернитесь к примеру с возвращаемым массивным массивом. Теперь кто-то, вероятно, может создать приложение, которое перебирает каждое значение внутри массива сообщений и печатает его. Если API обновлен, чтобы добавить только один дополнительный элемент к этому массиву сообщений, тогда код приложения сломается, поскольку он будет печатать какое-то новое поле, которого, вероятно, не должно быть. Если порядок элементов в массиве сообщений, возвращаемых API, изменится, это также нарушит код приложения. Таким образом, возврат массива создает всевозможные зависимости, которые объект не может создать.

  • Функциональность

Внутри объекта может храниться информация, которая позволяет ему предоставлять вам полезные функции. Например, объект сообщения может быть достаточно умным, чтобы возвращать предыдущие или следующие сообщения. Массив никогда не сможет сделать этого за вас.

  • Гибкость

Все преимущества упомянутых выше объектов помогают создать более гибкую систему.

Мэтт Кринкло-Фогт
источник
10

У меня вопрос, почему они используют объекты вместо массивов?

Наверное, две причины:

  • WordPress довольно старый
  • массивы быстрее и в большинстве случаев занимают меньше памяти
  • легче сериализовать

Есть ли причина производительности для использования объекта?

Нет. Но есть много других причин, например:

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

ООП ! = АОП :)

(Например, в Ruby все является объектом. PHP ранее был процедурным языком / языком сценариев.)

Takehin
источник
7

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

Объект (даже если это всего лишь экземпляр stdClass) является представлением одной вещи. В WordPress это может быть запись, комментарий или пользователь. С другой стороны, массив - это набор вещей. (Например, список сообщений.)

Исторически сложилось так, что PHP не имел хорошей поддержки объектов, поэтому массивы стали довольно мощными на раннем этапе. (Например, возможность иметь произвольные ключи, а не просто нулевая индексация.) Благодаря поддержке объектов, доступной в PHP 5, разработчики теперь могут выбирать между использованием массивов или объектов в качестве хранилищ значений ключей. Лично я предпочитаю подход WordPress, поскольку мне нравится синтаксическая разница между «сущностями» и «коллекциями», которые предоставляют объекты и массивы.

Себ Поллард
источник
5

У меня вопрос, почему они (Wordpress) используют объекты вместо массивов?

Это действительно хороший вопрос, на который нелегко ответить. Я могу только предположить, что в Wordpress часто используются stdClassобъекты, потому что они используют класс базы данных, который по умолчанию возвращает записи как stdClassобъект. Привыкли (8 лет и больше) и все. Я не думаю, что за этим простым фактом стоит что-то еще.

синтаксический сахар для ассоциативных массивов - Зеев Сураски о стандартном объекте начиная с PHP 3

  • stdClassобъекты на самом деле не лучше массивов. Они почти такие же. Это по некоторым историческим причинам языка, так как stdClassобъекты действительно ограничены и на самом деле являются лишь своего рода ценными объектами в очень простом смысле.
  • stdClassобъекты хранят значения для своих членов, как массив для каждой записи. Вот и все.
  • Только фанаты PHP могут создавать stdClassобъекты с закрытыми членами. От этого не будет особой пользы - если таковая вообще есть.
  • stdClassу объектов нет методов / функций. Так что никакого использования этого в Wordpress.
  • По сравнению с array, есть гораздо менее полезные функции для работы со списком или полуструктурированными данными.

Однако, если вы привыкли к массивам, просто приведите:

$array = (array) $object;

И вы можете получить доступ к данным, ранее являвшимся объектом, в виде массива. Или вам нравится наоборот:

$object = (object) $array;

Что приведет к удалению только недопустимых имен членов, например чисел. Так что будьте осторожны. Но я думаю, вы понимаете общую картину: особой разницы нет, если речь идет о массивах и объектах stdClass.

Связанный:

hakre
источник
4
  1. Так код выглядит круче
  2. Объекты передаются по ссылке
  3. Объекты более строго типизированы, чем массивы, поэтому меньше подвержены ошибкам (или выдают значимое сообщение об ошибке при попытке использовать несуществующий элемент)
  4. Все современные IDE имеют автозаполнение, поэтому при работе с определенными объектами IDE многое делает за вас и ускоряет работу.
  5. Легко инкапсулируйте логику и данные в одном и том же блоке, где с массивами вы храните данные в массиве, а затем используете набор различных функций для их обработки.
  6. Наследование. Если у вас будет аналогичный массив с почти, но не похожей функциональностью, вам придется продублировать больше кода, чем если вы собираетесь делать это с объектами

Возможно, еще одна причина, о которой я подумал

Итай Моав -Малимовка
источник
«# Объекты проходят по ссылке»: это неправильно. Объекты не передаются в качестве ссылки на переменную PHP. Они никогда этого не делали.
hakre
@hakre - ты на php4? или поясните, что вы имеете в виду.
Итай Моав -Малимовка
Не то чтобы wordpress не был PHP 4 до недавнего времени, но в PHP 4 или PHP 5 объекты не передаются в качестве ссылок: «Одна из ключевых точек ООП PHP5, о которой часто упоминается, заключается в том, что« объекты по умолчанию передаются по ссылкам » . Это не совсем так. Этот раздел исправляет эту общую мысль с помощью нескольких примеров ". Объекты и отсылки
hakre
@hakre - я понимаю, что вы имеете в виду, но для всех целей язык ведет себя так, как будто вы передаете только ссылки.
Итай Моав -Малимовка
4

Объекты намного мощнее, чем могут быть массивы. К каждому объекту как экземпляру класса могут быть прикреплены функции. Если у вас есть данные, которые нужно обработать, вам нужна функция, выполняющая обработку. С массивом вам нужно будет вызвать эту функцию в этом массиве и, следовательно, самостоятельно связать логику с данными. С объектом эта ассоциация уже создана, и вам больше не нужно о ней заботиться.

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

Никто не уходит от ЮВ
источник
Wordpress возвращает объекты класса StdClass. Эти объекты не имеют ничего общего с тем, что вы выделяете. Например, у них нет функций и нет наследования. А в случае Wordpress все переменные класса общедоступны.
hakre
Да это правда. Я думаю, что в этом случае это, как утверждали другие, просто в зависимости от того, что вы предпочитаете. Я не использую wordpress, но, вероятно, они инкапсулируют все вызовы базы данных и поэтому не могут предоставить какой-либо специализированный класс для возврата. Но мой ответ был в целом, и я думаю, что аналогичные соображения были сделаны производителями ... Или они просто бросили монетку.
Никто не уезжает из SE
Они просто используют вспомогательный класс базы данных, который stdClassпо умолчанию возвращает объекты, начиная с ок. 8 лет. Если вы хотите получить массив, вам нужно установить необязательный параметр для его получения.
hakre
3

Есть несколько причин для возврата объектов:

  1. Написание $myObject->propertyтребует меньшего количества "служебных" символов, чем$myArray['element']

  2. Объект может возвращать данные и функциональность; массивы могут содержать только данные.

  3. Включить цепочку: $myobject->getData()->parseData()->toXML();

  4. Более простое кодирование: автозаполнение IDE может предоставлять подсказки по методам и свойствам для объекта.

С точки зрения производительности массивы часто быстрее, чем объекты. Помимо производительности, есть несколько причин использовать массивы:

  1. Функциональные возможности, предоставляемые семейством функций array _ * (), могут в некоторых случаях сократить объем необходимого кодирования.

  2. Такие операции, как count () и foreach (), могут выполняться с массивами. Объекты этого не предлагают (если они не реализуют Iterator или Countable ).

Джордж Камминс
источник
2

Обычно этого не происходит из-за соображений производительности. Обычно объекты стоят больше, чем массивы.

Для многих API это, вероятно, связано с объектами, обеспечивающими другие функции, помимо механизма хранения. В противном случае это вопрос предпочтений, и на самом деле нет никакой пользы от возврата объекта по сравнению с массивом.

Simshaun
источник
В PHP5 разница в производительности между массивами и объектами незначительна.
Джастин ᚅᚔᚈᚄᚒᚔ
2

Массив - это просто индекс значений. В то время как объект содержит методы, которые могут генерировать результат за вас. Конечно, иногда вы можете получить доступ к значениям объектов напрямую, но «правильный способ сделать это» - обратиться к методам объектов (функция, работающая со значениями этого объекта).

$obj = new MyObject;
$obj->getName();   // this calls a method (function), so it can decide what to return based on conditions or other criteria

$array['name'];   // this is just the string "name". there is no logic to it. 

Иногда вы напрямую обращаетесь к переменным объекта, это обычно не одобряется, но до сих пор случается довольно часто.

$obj->name;   // accessing the string "name" ... not really different from an array in this case.

Однако учтите, что класс MyObject не имеет переменной с именем 'name', но вместо этого имеет переменные first_name и last_name.

$obj->getName();  // this would return first_name and last_name joined.
$obj->name;  // would fail...
$obj->first_name; 
$obj->last_name; // would be accessing the variables of that object directly.

Это очень простой пример, но вы можете видеть, к чему все идет. Класс предоставляет набор переменных и функций, которые могут работать с этими переменными, и все это внутри автономного логического объекта. Экземпляр этой сущности называется объектом, и он вводит логику и динамические результаты, которых у массива просто нет.

Ник Дженнингс
источник
1

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

Итак, главная причина в том, что ООП - отличная парадигма. Я написал статью о том, почему использование ООП - хорошая идея, и объясняя эту концепцию, вы можете посмотреть здесь: http://tomsbigbox.com/an-introduction-to-oop/

В качестве незначительного плюса вы также вводите меньше, чтобы получить данные от объекта - $ test-> data лучше, чем $ test ['data'].

Том Уолтерс
источник
1

Я не знаком с прессой слов. Многие ответы здесь предполагают, что сильная сторона объектов - это способность содержать функциональный код. При возврате объекта из вызова функции / API он не должен содержать служебных функций. Просто свойства.

Сила возврата объектов заключается в том, что все, что стоит за API, может измениться без нарушения кода.

Пример: вы получаете массив данных с парами ключ / значение, ключ представляет столбец БД. Если столбец БД будет переименован, ваш код сломается.

Джош Джонсон
источник
1

Я запускаю следующий тест на php 5.3.10 (windows):

for ($i = 0; $i < 1000000; $i++) {
    $x = array();
    $x['a'] = 'a';
    $x['b'] = 'b';
}

и

for ($i = 0; $i < 1000000; $i++) {
    $x = new stdClass;
    $x->a = 'a';
    $x->b = 'b';
}

Скопировано с http://atomized.org/2009/02/really-damn-slow-a-look-at-php-objects/comment-page-1/#comment-186961

Вызов функции для 10 одновременных пользователей и 10 раз (для получения среднего значения), затем

  • Массивы: 100%
  • Объект: 214% - 216% (в 2 раза медленнее).

AKA, объект все равно мучительно медленный. ООП сохраняет порядок, однако его следует использовать осторожно.

Что Wordpress применяет ?. Что ж, оба решения используют объекты, массивы и объекты и массивы, Class wpdb использует более позднее (и это сердце Wordpress).

магалланы
источник
Вы должны увидеть сравнение на PHP 5.4. Производительность объектов выдающаяся, а иногда даже быстрее, чем у массивов.
Санкет Саху
0

Он следует принципу упаковки и распаковки ООП. Хотя такие языки, как Java и C #, поддерживают это изначально, PHP - нет. Однако это может быть реализовано в некоторой степени в PHP, но не очень красноречиво, поскольку сам язык не имеет конструкций для его поддержки. Наличие типов боксов в PHP может помочь в создании цепочек, сохранении всего объектно-ориентированного подхода и позволяет использовать подсказки типов в сигнатурах методов. Обратной стороной являются накладные расходы и тот факт, что теперь у вас есть дополнительная проверка с помощью конструкции «instanceof ». Наличие системы типов также является плюсом при использовании инструментов разработки с поддержкой intellisense или кода, таких как PDT. Вместо того, чтобы искать метод в google / bing / yahoo, он существует для объекта, и вы можете использовать этот инструмент для создания раскрывающегося списка.

ЛЕМУЭЛЬ АДАН
источник
0

Хотя утверждения о том, что объекты являются чем-то большим, чем просто данные, действительны, поскольку они обычно являются данными и поведением, есть по крайней мере один шаблон, упомянутый в «Шаблонах архитектуры корпоративных приложений» Мартина Фаулера, который применим к этому типу cenario, в котором вы переносите данные из одной системы (приложение, стоящее за API) и другой (вашего приложения).

Это объект передачи данных - объект, который переносит данные между процессами, чтобы уменьшить количество вызовов методов.

Итак, если возникает вопрос, должны ли API возвращать DTO или массив, я бы сказал, что если стоимость производительности незначительна, вы должны выбрать вариант, который более удобен в обслуживании, который, я бы сказал, является вариантом DTO ... но, конечно, вы также необходимо учитывать навыки и культуру команды, которая разрабатывает вашу систему, а также поддержку языка или среды IDE для каждого из вариантов.

Витор Сильва
источник