2011-04-19 49 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

相關問題