Когда следует использовать stdClass и когда я должен использовать массив в коде php oo?

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

Есть ли ситуации, когда лучше использовать один вместо другого?

Какие преимущества я получу для использования stdClass вместо массивов?


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

Ответ 1

Обычный подход

  • Используйте объекты при возврате определенной структуры данных с фиксированными ветвями:

     $person
       -> name = "John"
       -> surname = "Miller"
       -> address = "123 Fake St"
    
  • Используйте массивы при возврате списка:

      "John Miller"
      "Peter Miller"
      "Josh Swanson"
      "Harry Miller"
    
  • Используйте массив объектов при возврате списка структурированной информации:

      $person[0]
        -> name = "John"
        -> surname = "Miller"
        -> address = "123 Fake St"
    
      $person[1]
        -> name = "Peter"
        -> surname = "Miller"
        -> address = "345 High St"
    

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

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

@Deceze делает несколько полезных моментов в том, когда использовать объект (проверка, проверка типов и будущие методы).

Ответ 2

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

Ответ 3

Я не думаю, что есть разумное преимущество использования stdClass над массивом, пока ваше единственное намерение - вернуть несколько произвольных типов данных из вызова функции.

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

function fn1() { return array(1,2); }
function fn2() { return array('one' => 1, 'two' => 2); }
function fn3() { return (object) array(1,2); }
function fn4() { return (object) array('one' => 1, 'two' => 2); }

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

Если вы хотите использовать объекты любой ценой, вы можете использовать ArrayObject или SplFixedArray, но если вы посмотрите на их API, скажете ли вы, что вам нужна их функциональность для простой задачи возврата случайных нескольких значений? Я так не думаю. Не поймите меня неправильно: если вы хотите использовать stdClass, используйте его. Не похоже, что это сломает что угодно. Но вы тоже ничего не выиграли. Чтобы добавить хотя бы некоторую выгоду, вы можете создать для этого отдельный класс с именем ReturnValues.

Может быть простой класс тегов

class ReturnValues {}

или что-то более функциональное

class ReturnValues implements Countable
{
    protected $values;
    public function __construct() { $this->values = func_get_args(); }
    public function __get($key) return $this->values[$key]; }
    public function count() { return count($this->values); }
}

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

class FooReturnValues extends ReturnValues
{
    public function getFoo() { return $this->values['foo']; }
    public function getBar() { return $this->values['foo']; }
}

Теперь разработчику просто нужно взглянуть на API, чтобы узнать, какие из следующих значений foo() вернутся. Конечно, необходимость писать конкретные классы ReturnValue для каждой операции, которая могла бы возвращать несколько значений, могла бы стать утомительной быстро. И лично я нахожу это переоцененным для первоначальной цели.

В любом случае, надеюсь, что это имеет смысл.

Ответ 4

Ну, есть 3 отличия:

  • они имеют идентичность. поэтому значение по умолчанию для передачи аргументов массива - это вызов по значению и для вызова объектов путем совместного использования.
  • существует семантическая разница. Если вы используете объект, любой, кто читает код, понимает, что это значение представляет некоторую определенную модель, а массив должен действовать как коллекция или карта.
  • И последнее, но не менее важное: рефакторинг становится значительно проще. Если вы хотите использовать конкретный класс, а не stdClass, все, что вам нужно сделать, это создать экземпляр другого класса. Что также позволяет добавлять методы.

Greetz
back2dos

Ответ 5

Я нахожу объекты stdClass над массивами полезными, когда мне нужно, чтобы мой код был чистым и несколько читабельным для чтения. Возьмем, например, функцию getProperties(), которая возвращает набор свойств, например данные о человеке (имя, возраст, пол). Если getProperties() вернет ассоциативный массив, если вы хотите использовать одно из возвращаемых свойств, вы должны написать две инструкции:

$data = getProperties();
echo $data['name'];

С другой стороны, если getProperties() возвращает stdClass, вы можете записать это только одной инструкцией:

echo getProperties()->name;

Ответ 6

Единственный ЦЕЛЬ, который я могу найти, - это:

json_decode использует stdClass по умолчанию, поэтому мы, смертные в userland, должны использовать stdClass для подобных ситуаций.

Ответ 7

В тестах массива vs stdclass они обрабатывают динамические свойства php медленнее, чем ассоциативные массивы. Я не говорю об этом, чтобы утверждать, что микро-оптимизация, но если вы собираетесь это сделать, вам лучше определить dataclass без каких-либо методов и установить общедоступные свойства. Esp, если вы используете php 5.4+. Под капотом определенные свойства отображаются непосредственно в массив c без хеш-таблицы, где динамические должны использовать хеш-таблицу.

У этого есть дополнительный бонус, который позже станет полноценным классом без какой-либо серьезной переделки интерфейса.