【问题标题】:In PHP, are objects methods code duplicated or shared between instances?在 PHP 中,对象方法代码是否在实例之间重复或共享?
【发布时间】:2011-12-11 07:50:34
【问题描述】:

在 PHP 中,如果你创建一个对象数组,对象方法(不是数据成员)是为数组中的每个对象实例复制的,还是只复制一次?我会假设出于记忆的原因,后者是正确的;我只是想向 StackOverflow 社区确认这是真的。

例如,假设我有一个带有几个方法的类 MyClass,即

class MyClass {
    public $data1;
    private $data2;
    public function MyClass($d1, $d2) { 
        $this->data1=$d1;   $this->data2=$d2;
    }
    public function method1() {  }
    public function method2() {  }
}

显然,实际上method1() 和method2() 不是空函数。 现在假设我创建了一个由这些对象组成的数组:

$arr = array();
$arr[0] = & new MyClass(1,2);
$arr[1] = & new MyClass(3,4);
$arr[2] = & new MyClass(5,6);

因此,PHP 为三个对象实例中的每一个在内存中存储了三组数据成员。我的问题是,PHP 是否还为 $arr 的 3 个元素中的每一个存储了 3 次 method1() 和 method2()(以及构造函数)的副本?我正在尝试确定一个包含约 200 个对象的数组是否会过于占用内存,因为必须在内存中存储每个方法的 200 个副本。

感谢您的宝贵时间。

【问题讨论】:

  • 根据定义,方法肯定是对过程的引用?在这种情况下,过程的机制将只定义一次(当你加载类时,not 当你实例化一个对象时)并且所有实例都将简单地指向该过程。这纯粹是猜测,但我看不出它是任何类型的方法/函数的任何其他方式,除非它是一个闭包。
  • 嗯。好问题。想知道在这些方法中定义的任何静态变量会发生什么。它是由方法的每个实例共享的一个静态变量,还是每个实例都有自己唯一的静态变量。
  • @DaveRandom 在 Javascript 中,当您定义一个类时,方法会嵌入到对象中。它们的内容不会在实例之间“共享”。
  • @Matthieu 同意,但是 Javascript 是一个完全不同的球类游戏,因为 JS 中的或多或少的 everything 本身就是一个对象——包括方法。但同样取决于您如何定义方法 - 如果您这样做 String.prototype.methodName = function () {}; 每个字符串对象都有一个名为 methodName 的方法,但它们并不都有自己的过程副本,它们将调用属于 @987654325 的方法@。在您执行 mystr.methodName = function () {}; 并覆盖该方法之前,mystr 拥有它自己的副本。但是对于 PHP(我相信)我的说法是正确的。

标签: php arrays object methods


【解决方案1】:

根据定义(即你的代码),一个函数只存在一次。这就是您生成代码(而不是数据)的原因。

但是,您随后可以使用您的代码生成大量数据。但那是另一回事了;)。

因此,除非您不需要在对象之间复制代码,否则您的函数只会存在一次。独立于您创建的代码的实例数量。只有与代码关联的数据(类成员)是重复的。

听起来公平吗?

顺便说一句:

$arr[0] = & new MyClass(1,2);

给你一个严格的标准错误。您不能使用 new 关键字分配引用/别名。可能这种编写方式受到 PHP 4 代码的影响,但自从 PHP 5 引入对象存储后,这种情况发生了变化。

【讨论】:

  • “根据定义,一个函数只存在一次” > 不,例如在 Javascript 中不是这种情况,请参阅我的答案。但是,在 PHP 中确实如此。
  • 那么你应该阅读我的评论......我说的是“例如”。只是你说错了,一个函数并不总是存在一次。我认为 OP 提出了一个有趣的问题,因为根据语言的不同,答案并不总是相同,因此值得“挑剔”和精确。 (如果你愿意,可以怒投反对,这是非常成熟的)
  • 感谢您对严格标准错误的提醒。我对 PHP5 编程相当陌生,我很欣赏这个提示。
  • 来自 OP:嗯,共识似乎是函数只定义一次,无论每个对象的实例数量如何。这正是我所期望的。感谢大家的帮助。顺便说一句,我已经有一段时间没有在 Stackoverflow 论坛上发帖了。如果有办法标记线程已解决,请告诉我。谢谢!
【解决方案2】:

方法内容只会在内存中存储一​​次。每个 PHP 对象(上述类的)都会引用该方法。

所以总结一下:如果您打算拥有很多对象,则不必关心方法的内存大小。只关心对象属性的内存大小。

例如,这与 Javascript 不同,其中每个类定义的方法都包含在每个实例中。但是,如果您在其原型中定义一个方法,则该方法由所有类实例共享(当然在内存中更轻)。请参阅此链接:http://webdevelopersjournal.com/articles/jsintro3/js_begin3.html

【讨论】:

  • 你所说的关于 javascript 是错误的。这不适用于您对所有 javascript 解释器的描述,在这种情况下,您实际上应该命名正确的语言名称和版本。
  • @hakre 你介意更精确吗??
猜你喜欢
  • 2014-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-24
相关资源
最近更新 更多