2011-04-19 52 views
4
<?php 
class A { 
    public function instanceFunc() { 
    echo "instance"; 
    } 

    public static function staticFunc() { 
    echo "static"; 
    } 
} 

A::instanceFunc(); // instance 
$a = new A(); 
$a->staticFunc(); // static 

这意味着在PHP中静态方法和实例方法根本没有什么不同。 Zend甚至没有抱怨(没有警告)。PHP的静态成员和实例成员似乎没有什么不同。为什么PHP这样做(没有警告)?

在Zend引擎中。静态方法和实例方法都保存在zend_class_entry.function_table中。

为什么PHP的行为如此?这是一个错误或功能?

+4

测试你的代码让我哭了... – Shoe 2011-04-19 17:18:46

+0

套用伊恩·马尔科姆:“仅仅因为你可以并不意味着你应该” :)的 – 2011-04-19 17:38:19

+0

可能重复[是否在PHP的静态方法与非静态方法有什么区别?(http://stackoverflow.com/questions/2439036/does-static-method-in-php-have-any-difference -with-非静态方法) – danorton 2014-03-25 18:58:38

回答

1

我不知道为什么它不会发出警告或至少发生错误。但是,静态和实例存在一些主要差异。静态方法不能使用非静态的类变量。通过添加一个非静态的公共/私有变量并试图在staticFunc中回显它会导致错误,这很容易测试。

我认为主要目标是了解两者之间的差异以及如何正确使用它们。至于为什么PHP至少没有提出通知,我不知道,也许是因为它的悠闲本性。我对有更多知识的人可以给予的回应感兴趣,这只是一些额外的信息。

我确实测试了它的完整错误报告,并且确实没有发出通知或警告。


UPDATE

做一些测试,它好像当你调用一个非标记为静态函数,你仍然不能使用私有/公共变量静电功能。对于正常的功能,这很可能会将它们错误地排除。这可能是错误或通知从未抛出的原因。然而,它会很好地抛出一些关于它的事情,因为以这种方式使用非标记的静态函数肯定不好。

3

这是潜在的重复Does static method in PHP have any difference with non-static method?

如果您启用了E_STRICT警告,您将收到一条错误消息,否则,您可以静静地调用非静态方法,就好像它是静态的。正如在这里的答案和另一个问题中所提到的那样,现实世界中的静态/非静态方法在访问$thisself时不会变得太远,因为它被写入了期望。

参考文档: http://www.php.net/manual/en/language.oop5.static.php

这里的东西一起玩:

http://codepad.org/Gbu9T6Zv

+0

1,漂亮明知严格捕获它。 – 2011-04-19 17:49:08

+0

调用静态方法instancely不会有事 – reeze 2011-04-24 03:38:28

+0

@reeze,我不确定您的评论的意思,但也绝对没有错,通过一个实例对象调用静态方法和_everything_情况完全一样,如果它是通过调用类文字。 – danorton 2014-03-25 18:55:52

2

如果您尝试运行下面的代码,并期待在回溯输出,你会看到PHP转换instanceFunc ()在静态上下文中调用时使用静态方法。但是,在实例上下文中,它会将其视为实例调用。

如果您将实例变量引入mix(删除注释掉的行),那么当从静态调用调用instanceFunc()时会遇到致命错误。

这意味着PHP允许所有本质上是静态的方法(没有实例变量可以处理)从静态上下文中调用,只要此合约被破坏,将会产生错误。因此,使用静态函数似乎只是与其他面向对象语言保持一致的良好实践。

至于staticFunc()两个呼叫显示,PHP解释这些静态调用,这是可以预料的。

class A { 
    private $x = 5; 
    private $y = 6; 
    private $z; 
    public function instanceFunc() { 
    //$this->z = $this->y * $this->x; 
    //echo $this->z; 
    var_dump(reset(debug_backtrace())); 
    } 

    public static function staticFunc() { 
    var_dump(reset(debug_backtrace())); 
    } 
} 
$a = new A(); 
A::instanceFunc(); // static call of intended instance method 
$a->instanceFunc(); // instance call of instance method 
A::staticFunc(); 
$a->staticFunc(); 

示例输出(带有注释运行的代码):

array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(19) ["function"]=> string(12) "instanceFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } } 
array(7) { ["file"]=> string(59) "test.php" ["line"]=> int(22) ["function"]=> string(12) "instanceFunc" ["class"]=> string(1) "A" ["object"]=> object(A)#8 (3) { ["x:private"]=> int(5) ["y:private"]=> int(6) ["z:private"]=> NULL } ["type"]=> string(2) "->" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(24) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } } 
array(6) { ["file"]=> string(59) "test.php" ["line"]=> int(26) ["function"]=> string(10) "staticFunc" ["class"]=> string(1) "A" ["type"]=> string(2) "::" ["args"]=> array(0) { } } 
+0

回溯有趣的东西,+1。在的事实,光这样做会抛出一个E_STRICT错误而已,我假定这是保持一些遗留/向后兼容的原因 - 的意图,最终消除它。否则,“将此方法转换为静态”行为是无稽之谈 - 你对此完全正确,但这完全是无稽之谈! – 2011-04-19 17:53:54

+0

我同意,这是荒谬的,但PHP不是天生的面向对象的语言,因此我想,你这个“错误”现有遗留原因是正确的怀疑。 – GordyD 2011-04-19 18:03:00

相关问题