72

在工作中的大重构期间,我希望引入 stdClass ***** 作为从函数返回数据的一种方式,并且我试图找到非主观的论据来支持我的决定。

有没有什么情况下最好使用一种而不是另一种?

使用 stdClass 而不是数组我会得到什么好处?


有人会说函数必须尽可能少且特定才能返回一个值。我使用 stdClass 的决定是暂时的,因为我希望从长远来看为每个进程找到正确的值对象。

4

7 回答 7

63

通常的做法是

  • 返回具有固定分支的已定义数据结构时使用对象:

     $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 对何时使用对象(验证、类型检查和未来方法)提出了许多要点。

于 2010-07-07T10:12:13.867 回答
44

stdClass恕我直言,用来实现与数组相同的功能并不是很有用,它只会增加对象的开销,而没有任何真正的好处。您还错过了许多有用的数组函数(例如array_intersect)。您至少应该创建自己的类以启用类型检查,或向对象添加方法以使其值得使用对象。

于 2010-07-07T10:13:19.920 回答
18

只要您的唯一目的是从函数调用返回多个任意数据类型,我认为使用 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 相比,它也有一个明确定义的目的(这有点虚伪,不是吗)。两者都只有一个隐式接口,因此您必须查看文档或函数体才能知道它们将包含什么。

如果您想不惜一切代价使用对象,您可以使用ArrayObjectSplFixedArray,但是如果您查看它们的 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 类可能会很快变得乏味。就个人而言,我发现这在最初的目的上被过度设计了。

无论如何,希望这有任何意义。

于 2010-07-09T21:06:51.623 回答
4

嗯,有3个区别:

  • 他们有一个身份。这就是为什么传递数组参数的默认值是按值调用而对象是按共享调用的原因。
  • 存在语义差异。如果你使用一个对象,任何读过代码的人都会明白,这个值代表了某种实体的模型,而一个数组应该充当一个集合或映射
  • 最后但并非最不重要的一点是,重构变得非常容易。如果你想使用一个具体的类而不是 stdClass,你所要做的就是实例化另一个类。它还允许您添加方法。

问候
back2dos

于 2010-07-07T13:04:50.797 回答
2

我能找到的唯一客观的信任投票是:

json_decode默认情况下使用 stdClass,因此我们在用户空间中的凡人应该在类似情况下使用 stdClass。

于 2014-04-24T16:14:22.887 回答
1

当我需要保持我的代码干净并且有点类似句子的可读性时,我发现数组上的 stdClass 对象很有用。以返回一组属性的函数为例,比如getProperties()关于一个人的数据(姓名、年龄、性别)。如果getProperties()将返回一个关联数组,当您想使用返回的属性之一时,您将编写两条指令:

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

另一方面,如果getProperties()返回一个 stdClass ,那么你可以只用一条指令来写:

echo getProperties()->name;
于 2012-09-15T14:51:29.057 回答
1

在数组与标准类的测试中,php 处理动态属性的方式比关联数组慢。我这样说并不是为了争论微优化,而是如果你要这样做,最好定义一个没有方法的数据类并设置公共属性。特别是如果您使用的是 php 5.4+。在引擎盖下定义的属性直接映射到没有哈希表的 ac 数组,而动态属性需要使用哈希表。

这有一个额外的好处,即后来成为一个完整的类,而无需任何主要的界面改造。

于 2014-08-10T19:17:25.183 回答