Навіщо повертати об’єкт замість масиву?


84

Я багато працюю в WordPress, і я помітив, що набагато більше функцій повертають об'єкти, ніж масиви. Результати бази даних повертаються як об'єкти, якщо ви спеціально не попросите масив. Помилки повертаються як об'єкти. Поза WordPress, більшість API надають вам об'єкт замість масиву.

Моє запитання: чому вони використовують об’єкти замість масивів? Здебільшого це не має великого значення, але в деяких випадках мені важче не тільки обробити предмети, але й обернути голову. Чи є причина використання продукту для використання об’єкта?

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


5
Мені цікаво це щодо недоліків об'єктів, таких як неможливість використання count()або array_*()функціонування на них (принаймні щодо збереження / повернення ключа => значення даних). Здається, ніхто про це не згадує, чи мені чогось не вистачає?
Wesley Murch

8
Об'єкти можна зробити перелічуваними та ітерабельними, застосувавши інтерфейси Countable або Iterator. Також перевірте php.net/manual/en/book.spl.php .
simshaun

Якщо SPL встановлено, і ви реалізуєте інтерфейс, що підраховується для вашого класу об'єкта, ви можете зателефонувати count()до об'єкта.
Ніхто не від’їжджає від SE

2
У багатьох випадках масив навіть не має сенсу, тому що ви не повертаєте колекцію об'єктів або якусь колекцію, яка не легко імітується масивами. Коли у вас просто є послідовність інших значень і жодна зайва семантика не пов’язана, тоді, заради Бога, поверніть масив - але ви виявите, що це рідко буває.

8
@delnan та інші: Зверніть увагу, що @Dennis говорить про асоціативні масиви (вони ж. Словники, вони ж. Карти), а не про звичайні масиви (цілочисельний індекс). Вони є основною особливістю PHP і служать більш-менш тій самій меті, що і динамічні класи ( stdClass). Я не впевнений, що на це запитання є інша відповідь, крім "Оскільки програмісти, які працюють переважно в ООП, віддають перевагу семантиці використання об'єктів"
BlueRaja - Danny Pflughoeft

Відповіді:


62

Ось причини, чому я віддаю перевагу об’єктам загалом:

  • Об'єкти містять не тільки дані, але й функціональність.
  • Об'єкти мають (у більшості випадків) заздалегідь визначену структуру. Це дуже корисно для розробки API. Крім того, ви можете встановити властивості як загальнодоступні, захищені чи приватні.
  • об'єкти краще відповідають об'єктно-орієнтованому розвитку.
  • У більшості автозаповнення IDE працює лише для об’єктів.

Ось що читати:


3
перше посилання здається нічого доброго? Я маю на увазі, що це працює, але переходить до іншої статті
Гео

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 раніше був процедурною / мовою сценаріїв.)


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.

Пов’язані:


4
  1. Код виглядає таким чином крутішим
  2. Об'єкти передаються за посиланням
  3. Об'єкти набираються набагато сильніше, ніж масиви, отже, lees pron до помилок (або надає вам значуще повідомлення про помилку при спробі використовувати неіснуючий член)
  4. Усі IDE сьогодні мають автозаповнення, тому при роботі з визначеними об’єктами IDE робить багато для вас і пришвидшує процес
  5. Легко інкапсулюйте логіку та дані в одному вікні, де за допомогою масивів ви зберігаєте дані в масиві, а потім використовуєте набір різних функцій для їх обробки.
  6. Спадщина, якщо у вас буде подібний масив з майже, але не подібною функціональністю, вам доведеться продублювати більше коду, ніж якщо ви хочете це робити з об'єктами

Можливо, ще якась причина, про яку я думав


"# Об'єкти передаються за посиланням": Це неправильно. Об'єкти не передаються як посилання на змінну PHP. Вони ніколи цього не робили.
hakre

@hakre - ти на php4? або уточніть, будь ласка, що ви маєте на увазі.
Itay Moav -Malimovka

Ну не те, що wordpress до недавнього часу не був PHP 4, але в PHP 4 або PHP 5 об'єкти не передаються як посилання: "Однією з ключових точок PHOP5 OOP, яку часто згадують, є те, що" об'єкти передаються за посиланнями за замовчуванням " . Це не зовсім так. Цей розділ виправляє цю загальну думку на деяких прикладах ". Об'єкти та посилання
hakre

@hakre - Я розумію, що ти маєш на увазі, але для всіх цілей мова поводиться так, ніби ти передаєш лише посилання.
Itay Moav -Malimovka

4

Об'єкти набагато потужніші, ніж можуть бути масиви. Кожен об'єкт як екземпляр класу може мати приєднані функції. Якщо у вас є дані, які потребують обробки, тоді вам потрібна функція, яка виконує обробку. За допомогою масиву вам доведеться викликати цю функцію в цьому масиві і, отже, самостійно прив’язати логіку до даних. З об’єктом ця асоціація вже зроблена, і вам більше не доведеться про це дбати.

Також вам слід врахувати принцип ОО приховування інформації. Не все, що повертається з бази даних або надходить до неї, має бути безпосередньо доступним.


Wordpress повертає об'єкти класу StdClass. Ці об’єкти не мають нічого спільного з тим, що ви виділяєте. Вони, наприклад, не мають жодних функцій і не мають спадку. А у випадку Wordpress всі змінні класу є загальнодоступними.
hakre

Так це правда. Я думаю, що в цьому випадку це, як заявляли інші, лише залежно від того, що ви віддаєте перевагу. Я не люблю wordpress, але, мабуть, вони інкапсулюють усі виклики до бази даних, і тому не можуть надати жодного спеціалізованого класу для повернення. Але моя відповідь була загалом, і, думаю, подібні міркування були зроблені виробниками ... Або вони просто кинули монету.
Ніхто не від'їжджає від SE

Вони просто використовують допоміжний клас бази даних, який повертає stdClassоб’єкти за замовчуванням, оскільки ca. 8 років. Якщо ви хочете отримати масив, вам потрібно встановити необов’язковий параметр, щоб отримати його.
hakre

3

Існує кілька причин повернення об'єктів:

  1. Для написання $myObject->propertyпотрібно менше "накладних" символів, ніж$myArray['element']

  2. Об'єкт може повертати дані та функціональність; масиви можуть містити лише дані.

  3. Увімкнути ланцюжок: $myobject->getData()->parseData()->toXML();

  4. Простіше кодування: автозавершення IDE може надати підказки щодо методів та властивостей для об’єкта.

Що стосується продуктивності, масиви часто швидші за об'єкти. Окрім продуктивності, є кілька причин використання масивів:

  1. Функціональність, що надається масивом функцій сімейства _ * (), може в деяких випадках зменшити обсяг кодування.

  2. Такі операції, як count () і foreach (), можна виконувати над масивами. Об'єкти цього не пропонують (якщо вони не використовують Iterator або Countable ).


2

Зазвичай це не відбувається через причини ефективності. Як правило, об'єкти коштують дорожче масивів.

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


У 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 застосовує ?. Ну, обидва рішення використовують об'єкти, масиви та об'єкти та масиви, клас wpdb використовує пізніші (і це серце Wordpress).


Ви повинні побачити порівняння на PHP 5.4. Продуктивність об’єктів надзвичайна, а іноді навіть швидша, ніж масиви.
Санкет Саху

0

Він дотримується принципу боксу та розпакування боксу. Хоча такі мови, як Java та C #, підтримують це спочатку, PHP - ні. Однак це може бути здійснено певною мірою в PHP, але не красномовно, оскільки сама мова не має конструкцій для її підтримки. Наявність типів коробки в PHP може допомогти з ланцюжком, зберігаючи все об’єктно-орієнтоване та дозволяючи підказувати типи в підписах методів. Недоліком є ​​накладні витрати і той факт, що тепер у вас є додаткові перевірки, які потрібно виконати, використовуючи конструкцію "Üinstanceof". Наявність системи типів також є плюсом при використанні засобів розробки, які мають intellisense або допоміжний код, як PDT. Замість того, щоб шукати Google / bing / yahoo для методу, він існує на об’єкті, і ви можете використовувати інструмент для випадаючого списку.


0

Незважаючи на те, що пункти щодо об'єктів є не просто даними, є дійсними, оскільки це, як правило, дані та поведінка, у " Шаблонах архітектури корпоративних додатків" Мартіна Фаулера згадується принаймні один шаблон, який застосовується до цього типу кенаріо, в якому ви передаєте дані з однієї системи (програма, що стоїть за API), а іншої (ваша програма).

Це об’єкт передачі даних - об’єкт, який передає дані між процесами з метою зменшення кількості викликів методів.

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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.