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


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

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

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


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

7 64

7 ответов:

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

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

     $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 делает ряд хороших моментов о том, когда использовать объект (проверка, проверка типа и будущие методы).

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

Я не думаю, что есть какое-либо разумное преимущество использования 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 (который немного wishywashy, не так ли). Оба имеют только неявный интерфейс, поэтому вам нужно будет посмотреть документы или тело функции, чтобы узнать, что они будут содержать.

если вы хотите использовать объекты любой ценой, вы можете использовать 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); }
}

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

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

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

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

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

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

greetz
back2dos

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

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

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

echo getProperties()->name;

единственный объективный вотум доверия, который я могу найти, это:

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

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

Это имеет дополнительный бонус позже становится полным классом без какой-либо серьезной переработки интерфейса.