为什么要返回对象而不是数组?


84

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

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

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


5
对于对象的缺点,例如无法使用对象count()array_*()在对象上发挥作用(至少在存储/返回键=>值数据方面),我对此感到好奇。似乎没有人提起它,还是我错过了什么?
Wesley Murch

8
通过实现Countable或Iterator接口,可以使对象可计数和可迭代。还要查看php.net/manual/en/book.spl.php
simshaun 2011年

如果安装了SPL,并且您实现了可用于您的对象类的接口,那么您可以调用count()一个对象。
没有人离开SE

2
在许多情况下,数组甚至没有意义,因为您不返回对象的集合,也不是不容易用数组模拟的集合。当您仅具有其他值的序列并且没有关联的额外语义时,为方便起见,请返回一个数组-但您会发现这种情况很少见。

8
@delnan和其他人:请注意,@ Dennis在谈论的是关联数组,(又称字典,又称地图),而不是普通的(整数索引)数组。这些是PHP的核心功能,其用途与动态类(stdClass)大致相同。除了“因为主要在OOP中工作的程序员喜欢使用对象的语义”之外,我不确定该问题是否有答案
BlueRaja-Danny Pflughoeft

Answers:


62

这些就是为什么我通常更喜欢对象的原因:

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

这是要阅读的内容:


3
第一个链接似乎没有好处?我的意思是它的工作原理,但需要到不同的aritcle
地理

24

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

让我们来看几个例子。

  • 如果返回了数组,那么要么需要预先计算所有值,要么需要返回很多小值,您可以使用它们来构建更复杂的值。

考虑一个返回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数组中的项目顺序发生变化,这也会破坏应用程序代码。因此,返回数组会创建对象可能不会创建的各种可能的依赖关系。

  • 功能性

对象可以在其中保存信息,从而可以为您提供有用的功能。例如,发布对象可能足够聪明,可以返回上一个或下一个发布。数组永远无法为您做到这一点。

  • 灵活性

上面提到的对象的所有优点都有助于创建更灵活的系统。


10

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

可能有两个原因:

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

使用对象有性能上的原因吗?

不。但是还有很多其他原因,例如:

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

OOP!= AOP :)

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


7

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

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

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


5

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

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

语法糖关联数组 -泽弗·苏拉斯凯 关于标准对象因为PHP 3

  • stdClass对象并不是真的比数组更好。它们几乎相同。这是由于语言的某些历史原因,而且stdClass对象实际上是有限的,实际上只是非常基本意义上的某种价值对象
  • stdClass对象存储其成员的值,就像每个条目的数组一样。就是这样。
  • 只有PHP怪胎才能stdClass使用私有成员创建对象。这样做没有太大的好处-如果有的话。
  • stdClass对象没有任何方法/功能。因此,请勿在Wordpress中使用它。
  • 与相比array,处理列表或半结构化数据的有用功能要少得多。

但是,如果您习惯使用数组,则只需进行以下转换即可:

$array = (array) $object;

您可以访问以前作为对象的数据(作为数组)。或者您也喜欢它:

$object = (object) $array;

这只会删除无效的成员名称,例如数字。因此请多加注意。但是我认为您可以了解一下:只要有关于的数组和对象,就没有太大的区别stdClass

有关:


4
  1. 这样的代码看起来很酷
  2. 对象通过引用传递
  3. 对象的类型要强于数组,因此容易出错(或在尝试使用不存在的成员时给您有意义的错误消息)
  4. 当今所有的IDE都具有自动完成功能,因此在使用已定义的对象时,IDE会为您做很多事情并加快处理速度
  5. Easilly封装逻辑数据在同一数组中,在数组中,数组将数据存储在数组中,然后使用一组不同的函数来处理它们。
  6. 继承,如果您有一个具有几乎但不相似功能的相似数组,则必须复制更多代码,然后再使用对象

我可能还想过一些其他原因


“#对象通过引用传递”:是错误的。对象不作为PHP变量引用传递。他们从来没有。
hakre 2011年

@hakre-您在使用php4吗?或请详细说明您的意思。
Itay Moav -Malimovka,2011年

并不是说wordpress直到最近才成为PHP 4,而是在PHP 4或PHP 5中才通过对象作为引用:“经常提到的PHP5 OOP的关键点之一是“对象默认情况下是通过引用传递的”这不是完全正确。本节使用一些示例来纠正一般性思想。” 对象和引用
hakre 2011年

@hakre-我明白您的意思了,但出于所有目的,该语言的行为就像您仅传递引用一样。
Itay Moav -Malimovka,2011年

4

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

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


Wordpress返回该类的对象StdClass。这些对象与您突出显示的内容没有任何共同之处。例如,它们没有功能,也没有继承。对于Wordpress,所有类变量都是公共的。
hakre 2011年

是的,那是真的。我认为在这种情况下,就像其他人所说的,仅取决于您的偏好。我不喜欢wordpress,但可能它们封装了所有数据库调用,因此无法提供任何专门的类来返回。但是我的回答是一般性的,我认为制造商也有类似的考虑……或者他们只是投了一个硬币。
没有人远离SE

他们只使用数据库帮助程序类,stdClass从ca开始,该类默认情况下返回对象。8年。如果要获取数组,则需要设置一个可选参数来获取它。
hakre 2011年

3

返回对象的原因有几个:

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

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

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

  4. 简化编码:IDE自动补全功能可以为对象提供方法和属性提示。

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

  1. 在某些情况下,由array _ *()函数家族提供的功能可以减少所需的编码量。

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


2

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

对于许多API,它可能与提供存储功能以外的其他功能的对象有关。否则,这是一个优先事项,并且返回对象与数组相比并没有任何好处。


在PHP5中,数组和对象之间的性能差异很小。
贾斯汀(Justin)2011年

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类允许您拥有一个数据库对象,您可以使用大量内置函数(而不是过程方法)来操纵该数据库对象。

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

作为未成年人,您还可以键入更少的内容来从对象获取数据-$ test-> data比$ test ['data']更好。


1

我不熟悉文字印刷机。这里有许多答案表明,对象的强项就是能够包含功能代码。从函数/ API调用返回对象时,它不应包含实用程序函数。只是属性。

返回对象的优势在于,API背后的任何内容都可以更改而不会破坏您的代码。

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


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倍)。

再次,对象它仍然痛苦缓慢。OOP使事情保持整洁,但是应谨慎使用。

Wordpress正在应用什么?嗯,这两种解决方案都使用对象,数组和对象与数组,而wpdb使用后者(这是Wordpress的核心)。


您应该看到PHP 5.4上的比较。对象的性能非常出色,有时甚至比数组更快。
Sanket Sahu 2012年

0

它遵循OOP的装箱和拆箱原理。尽管诸如Java和C#之类的语言本身就支持此功能,但PHP不支持。但是,在某种程度上可以用PHP来实现,但这并不是因为语言本身没有支持它的构造而雄辩地做到的。在PHP中使用框类型可以帮助进行链接,使所有对象保持面向对象,并允许在方法签名中进行类型提示。缺点是开销,而且现在您需要使用“ instanceof”构造进行额外的检查。当使用具有智能感知或代码辅助功能的开发工具(例如PDT)时,拥有类型系统也是一个加号。无需在Google / bing / yahoo中找到该方法,它就存在于对象上,您可以使用该工具提供一个下拉菜单。


0

尽管关于对象不仅仅是数据的观点是有效的,因为它们通常是数据和行为,但在Martin Fowler的“企业应用程序体系结构模式”中至少提到了一种模式,该模式 适用于您要转移的这种情况来自一个系统(API背后的应用程序)和另一个系统(您的应用程序)的数据。

它的数据传输对象-在进程之间携带数据以减少方法调用数量的对象。

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.