【问题标题】:Why return object instead of array?为什么返回对象而不是数组?
【发布时间】:2011-10-06 08:39:00
【问题描述】:

我在 WordPress 中做了很多工作,我注意到返回对象的函数远多于数组。除非您特别要求数组,否则数据库结果将作为对象返回。错误作为对象返回。在 WordPress 之外,大多数 API 都会为您提供对象而不是数组。

我的问题是,为什么他们使用对象而不是数组?在大多数情况下,这并不重要,但在某些情况下,我发现对象不仅更难处理,而且更难缠住我的脑袋。使用对象是否有性能原因?

我是一名自学成才的 PHP 程序员。我有文科学位。如果我遗漏了计算机科学的一个基本方面,请原谅我。 ;)

【问题讨论】:

  • 我很好奇对象的缺点,比如不能对它们使用count()array_*() 函数(至少在关于存储/返回键 => 值数据)。似乎没有人提到它,还是我错过了什么?
  • 通过实现 Countable 或 Iterator 接口可以使对象可数和可迭代。也请查看php.net/manual/en/book.spl.php
  • 如果安装了 SPL 并且您为您的对象类实现了可计数的接口,那么您可以在对象上调用 count()
  • 在许多情况下,数组甚至没有意义,因为您不返回对象集合,或者一种不容易用数组模拟的集合。如果您只有一系列其他值且没有关联额外的语义,那么看在上帝的份上返回一个数组 - 但您会发现这种情况很少发生。
  • @delnan 和其他人:请注意@Dennis 谈论的是associative arrays,(又名字典,又名地图),而不是普通的(整数索引)数组。这些是 PHP 的核心特性,其用途与动态类 (stdClass) 大致相同。我不确定这个问题除了“因为主要从事 OOP 工作的程序员更喜欢使用对象的语义”之外还有其他答案

标签: php


【解决方案1】:

通常不会因为性能原因。通常,对象的成本高于数组。

对于很多 API,它可能与提供存储机制之外的其他功能的对象有关。否则,这是一个偏好问题,返回对象与返回数组实际上没有任何好处。

【讨论】:

  • 在 PHP5 中,数组和对象在性能上的差异是微不足道的。
【解决方案2】:

对象比数组更强大。 作为类的实例的每个对象都可以附加函数。 如果您有需要处理的数据,那么您需要一个进行处理的函数。 使用数组,您必须在该数组上调用该函数,因此将自己的逻辑与数据相关联。 有了一个对象,这个关联就已经完成了,你不必再关心它了。

您还应该考虑信息隐藏的 OO 原则。并非所有从数据库返回或进入数据库的内容都应该可以直接访问。

【讨论】:

  • Wordpress 返回 StdClass 类的对象。这些对象与您突出显示的内容没有任何共同之处。例如,它们没有功能,也没有继承。在 Wordpress 的情况下,所有类变量都是公共的。
  • 是的,这是真的。我认为在这种情况下,正如其他人所说,这取决于你喜欢什么。我不喜欢 wordpress,但可能它们封装了所有数据库调用,因此无法提供任何专门的返回类。但我的回答是笼统的,我认为制造商也有类似的考虑......或者他们只是扔了一枚硬币。
  • 他们只是使用一个数据库助手类,默认情况下返回 stdClass 对象,因为 ca。 8年。如果要获取数组,需要设置一个可选参数来获取。
【解决方案3】:
  1. 这样代码看起来更酷
  2. 对象通过引用传递
  3. 对象的类型比数组强,因此容易出错(或在您尝试使用不存在的成员时给您一个有意义的错误消息)
  4. 当今的所有 IDE 都具有自动完成功能,因此在处理已定义的对象时,IDE 可以为您做很多事情并加快处理速度
  5. 轻松地将逻辑数据封装在同一个盒子中,其中数组,您将数据存储在数组中,然后使用一组不同的函数对其进行处理。
  6. 继承,如果你有一个类似的数组,功能几乎但不相似,你必须复制更多的代码,然后如果你用对象来做

可能还有一些我想到的原因

【讨论】:

  • "# Objects pass by reference": 错了。对象不作为 PHP 变量引用传递。他们从来没有。
  • @hakre - 你在 php4 上吗?或者请详细说明您的意思。
  • 好吧,并不是说 wordpress 直到最近才不是 PHP 4,而是在 PHP 4 或 PHP 5 中,对象不会作为引用传递:“经常提到的 PHP5 OOP 的关键点之一是“默认情况下,对象是通过引用传递的”。这并不完全正确。本节通过一些示例来纠正这种普遍的想法。“ Objects and references
  • @hakre - 我明白你的意思,但出于所有目的,该语言的行为就像你只传递引用一样。
【解决方案4】:

返回对象有几个原因:

  1. 编写$myObject->property 需要的“开销”字符少于$myArray['element']

  2. 对象可以返回数据和功能;数组只能包含数据。

  3. 启用链接:$myobject->getData()->parseData()->toXML();

  4. 更容易编码:IDE 自动补全可以为对象提供方法和属性提示。

在性能方面,数组通常比对象快。除了性能之外,使用数组还有几个原因:

  1. array_*() 系列函数提供的功能可以减少某些情况下所需的编码量。

  2. 可以对数组执行count() 和foreach() 等操作。对象不提供此功能(除非它们实现 IteratorCountable)。

【讨论】:

    【解决方案5】:

    在大多数情况下,对象与数组一样快,甚至比数组快,但在 PHP 中并没有明显的区别。主要原因是对象比数组更强大。面向对象的编程允许您创建对象并不仅存储数据,还存储其中的功能,例如在 PHP 中,MySQLi 类允许您拥有一个数据库对象,您可以使用大量内置函数而不是过程方法来操作该对象。

    所以主要原因是 OOP 是一个优秀的范例。我写了一篇关于为什么使用 OOP 是个好主意的文章,并解释了这个概念,你可以看看这里:http://tomsbigbox.com/an-introduction-to-oop/

    作为一个小优点,您还可以键入 less 从对象中获取数据 - $test->data 比 $test['data'] 更好。

    【讨论】:

      【解决方案6】:

      数组只是值的索引。而对象包含可以为您生成结果的方法。当然,有时您可以直接访问对象的值,但“正确的做法”是访问对象的方法(对对象的值进行操作的函数)。

      $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.
      

      这是一个非常简单的示例,但您可以看到它的发展方向。一个类提供了一组变量和可以对这些变量进行操作的函数,这些变量都在一个自包含的逻辑实体中。该实体的实例称为对象,它引入了数组根本没有的逻辑和动态结果。

      【讨论】:

        【解决方案7】:

        这些是我更喜欢对象的原因:

        • 对象不仅包含数据,还包含功能。
        • 对象(在大多数情况下)具有预定义的结构。这对于 API 设计非常有用。此外,您可以将属性设置为公共、受保护或私有。
        • 对象更适合面向对象的开发。
        • 在大多数 IDE 中,自动完成功能仅适用于对象。

        这里有一些东西可以阅读:

        【讨论】:

        • 第一个链接好像不行?我的意思是它有效,但需要不同的文章
        【解决方案8】:

        我的问题是,为什么他们(Wordpress)使用对象而不是数组?

        这确实是一个很好的问题,但不容易回答。我只能假设在 Wordpress 中使用stdClass 对象很常见,因为它们使用的数据库类默认情况下将记录作为stdClass 对象返回。他们已经习惯了(8 年及以上),仅此而已。我不认为这个简单的事实背后有更多的想法。

        关联数组的语法糖 -- Zeev Suraski about the standard object 自 PHP 3 起

        • stdClass 对象并不比数组好。它们几乎相同。这是由于语言的某些历史原因以及 stdClass 对象非常有限,实际上只是在非常基本的意义上类似于 value objects
        • stdClass 对象为它们的成员存储值,就像每个条目的数组一样。就是这样。
        • 只有 PHP 怪才能够创建具有私有成员的 stdClass 对象。这样做没有太多好处(如果有的话)。
        • stdClass 对象没有任何方法/功能。所以在 Wordpress 中没有使用它。
        • array 相比,处理列表或半结构化数据的有用函数要少得多。

        但是,如果您习惯于数组,只需强制转换:

        $array = (array) $object;
        

        您可以访问以前作为对象的数据,作为数组。或者你喜欢反过来:

        $object = (object) $array;
        

        这只会删除无效的成员名称,例如数字。所以要小心一点。但我想你明白了:只要是stdClass 的数组和对象,没有太大区别。

        相关:

        【讨论】:

          【解决方案9】:

          我的问题是,为什么他们使用对象而不是数组?

          可能有两个原因:

          • WordPress 已经很老了
          • 在大多数情况下,数组速度更快,占用的内存更少
          • 更容易序列化

          使用对象是否有性能原因?

          没有。但是还有很多很好的其他原因,例如:

          • 您可以将逻辑存储在对象(方法、闭包等)中
          • 您可以使用界面强制对象结构
          • IDE 中更好的自动完成功能
          • 您不会收到未定义数组键的通知
          • 最后,您可以轻松地将任何对象转换为数组

          OOP != AOP :)

          (例如,在 Ruby 中,一切都是对象。PHP 以前是过程/脚本语言。)

          【讨论】:

            【解决方案10】:

            在您从事大型软件项目数年之前,您可能不会深入理解这一点。许多新的计算机科学专业的学生会用所有正确的词(封装、数据功能和可维护性)给你一个答案,但很少有人会真正理解为什么拥有所有这些东西是好的。

            我们来看几个例子。

            • 如果返回数组,则需要预先计算所有值,或者需要返回大量小值,您可以使用这些值构建更复杂的值。

            考虑一个返回 WordPress 帖子列表的 API 方法。这些帖子都有作者,作者有姓名,电子邮件地址,甚至可能还有他们的传记简介。

            如果您要返回一个数组中的所有帖子,您要么必须限制自己返回一个帖子 ID 数组:

            [233, 41, 204, 111]

            或返回一个看起来像这样的大数组:

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

            返回 ID 列表的第一种情况对您没有多大帮助,因为您需要为每个 ID 进行 API 调用才能获取有关该帖子的一些信息。

            第二种情况会在 90% 的时间里获取比您需要的更多的信息,并且做更多的工作(尤其是如果这些字段中的任何一个构建起来非常复杂)。

            另一方面,一个对象可以让您访问您需要的所有信息,但实际上还没有提取这些信息。使用对象时,可以懒惰地确定字段的值(即在需要值时而不是事先)。

            • 数组公开的数据和功能比预期的要多

            回到返回海量数组的例子。现在有人可能会构建一个应用程序来遍历 post 数组中的每个值并打印它。如果更新 API 以向该 post 数组添加一个额外的元素,那么应用程序代码将会中断,因为它将打印一些它可能不应该打印的新字段。如果 API 返回的 post 数组中的项目顺序发生变化,也会破坏应用程序代码。因此,返回一个数组会创建对象不会创建的各种可能的依赖关系。

            • 功能性

            一个对象可以在其内部保存信息,这将允许它为您提供有用的功能。例如,一个帖子对象可能足够聪明,可以返回上一个或下一个帖子。数组永远无法为您做到这一点。

            • 灵活性

            上述对象的所有好处有助于创建更灵活的系统。

            【讨论】:

              【解决方案11】:

              出于概念而非技术原因,WordPress(以及相当数量的其他 PHP 应用程序)使用对象而不是数组。

              一个对象(即使只是 stdClass 的一个实例)是一个事物的表示。在 WordPress 中,可能是帖子、评论或用户。另一方面,数组是事物的集合。 (例如,帖子列表。)

              从历史上看,PHP 并没有很好的对象支持,因此数组在早期变得非常强大。 (例如,具有任意键的能力,而不仅仅是零索引。)借助 PHP 5 中提供的对象支持,开发人员现在可以选择使用数组或对象作为键值存储。就个人而言,我更喜欢 WordPress 方法,因为我喜欢对象和数组提供的“实体”和“集合”之间的语法差异。

              【讨论】:

                【解决方案12】:

                我不熟悉word press。这里的很多答案表明对象的优势在于能够包含功能代码。从函数/API 调用返回对象时,它不应包含实用程序函数。只是属性。

                返回对象的优势在于,API 背后的任何内容都可以在不破坏代码的情况下进行更改。

                示例:您得到一个包含键/值对的数据数组,键代表 DB 列。如果 DB 列被重命名,您的代码将会中断。

                【讨论】:

                  【解决方案13】:

                  它遵循OOP的装箱和拆箱原则。虽然 Java 和 C# 等语言本机支持这一点,但 PHP 不支持。然而,在某种程度上,它可以在 PHP 中完成,只是不是很有说服力,因为语言本身没有支持它的结构。在 PHP 中使用 box 类型有助于链接,保持一切面向对象,并允许在方法签名中进行类型提示。缺点是开销,而且您现在需要使用“instanceof”构造进行额外检查。使用具有智能感知或代码辅助(如 PDT)的开发工具时,拥有类型系统也是一个优势。该方法不必在 google/bing/yahoo 上搜索,它存在于对象上,您可以使用该工具提供下拉菜单。

                  【讨论】:

                    【解决方案14】:

                    我正在 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,对象它仍然是缓慢的痛苦。 OOP 使事情保持整洁,但应谨慎使用。

                    Wordpress 应用的是什么?好吧,这两种解决方案都是使用对象、数组和对象&数组,wpdb 类使用后者(它是 Wordpress 的核心)。

                    【讨论】:

                    • 你应该看到 PHP 5.4 的比较。对象的性能非常出色,有时甚至比数组更快。
                    【解决方案15】:

                    尽管关于对象不仅仅是数据的观点是有效的,因为它们通常是数据和行为,但Martin Fowler's "Patterns of Enterprise Application Architecture" 中至少提到了一种模式,适用于这种类型的场景,在这种场景中,您从一个传输数据系统(API 背后的应用程序)和另一个(您的应用程序)。

                    它是Data Transfer Object - 一个在进程之间携带数据以减少方法调用次数的对象。

                    因此,如果问题是 API 应该返回 DTO 还是数组,我会说如果性能成本可以忽略不计,那么您应该选择更易于维护的选项,我认为是 DTO 选项......但是当然,您还必须考虑开发系统的团队的技能和文化,以及每个选项的语言或 IDE 支持。

                    【讨论】:

                      猜你喜欢
                      • 2021-02-14
                      • 1970-01-01
                      • 2011-10-19
                      • 2018-03-23
                      • 1970-01-01
                      • 2013-08-20
                      • 1970-01-01
                      • 2020-04-11
                      • 2018-07-05
                      相关资源
                      最近更新 更多