2014-02-20 79 views
1

我正在做一個PHP實驗的小實驗,我遇到了這個奇怪的問題。功能調用自己無限?

類意的情況下,$實例,其$實例屬性分配本身一個實例是,但這種機制應該防止無限自我繁衍,似乎失敗了,這是發生的事情:

Fatal error: Maximum function nesting level of '100' reached, aborting!

<?php 
class SeemsLikeInfinity { 

public $instance; 

public function __construct() { 

    if ($this->instance == null) { 

     $this->instance = new self; 

    } 
} 

} 

$looping = new SeemsLikeInfinity(); 

?> 

爲什麼會出現這種情況? __construct僅創建一個空的類的新實例,因此具有空的$實例,因此再次創建該實例,使循環無限?

非常感謝您

回答

1

當你與「新」的關鍵字的對象,它會調用構造函數。如果在構造函數中使用new self,它將再次調用構造。造成無限循環。

當您使用new時會自動創建一個新實例,因此您不必存儲類似$this->instance的東西。變量$this是您的實例的

要記住的重要一點是該類的每個實例都有自己的變量$instance。所以它將永遠是空的。

現在,如果你正在嘗試做一個單身,你實際上必須使構造私有:

private function __construct() {} 

然後我們需要instance是一個靜態變量:

static private $instance; 

無無可以使用new關鍵字創建一個新對象。那麼接下來,我們需要提供一個靜態函數來創建一個實例:

static function newInstance() { 
    if (self::instance == null) { 
     self::instance = new self; 
    } 
    return self::instance; 
} 

現在你就用這個新的實例:

$x = SeemsLikeInfinity::newInstance(); 

現在有將永遠只能是一個SeemsLikeInfinity對象,你可以隨時訪問它與SeemsLikeInfinity::newInstance()

+0

謝謝,它試圖實現一個Singleton模式,但我可能錯了。 我知道$ this代表當前對象的實例,我試圖創建一個能夠使用$ object-> instance-> doSomething()訪問的對象,而實例包含$ object的一個實例。 – user3104270

+0

更新瞭如何正確創建單例。 –

+0

這也會導致'致命錯誤:當不在對象上下文中使用$ this'我相信...... – CD001

2

發生這種情況是因爲參數$實例始終爲空。每次在課堂內創建新對象。如果你想器具獨居,你應該__construct更改爲私人和使用一個靜態方法來創建只是一個對象

class SeemsLikeInfinity { 

    private static $instance; 

    private function __construct() { 
     // some action; 
    } 
    public static function generate_singleton(){ 
    if (self::$instance == null) { 
     self::$instance = new self; 
    } 
    return self::$instance 
    } 
} 

$singleton = SeemsLikeInfinity::generate_singleton(); 
// here you have singleton and you cant create more tha one object 
+0

我可能是錯的 - 但這會導致一個'致命的錯誤:當不在對象上下文中時使用$ this' – CD001

0

,你必須使用靜態變量,而不是$this的原因是,$this相對於只對當前對象 - 每次創建新對象SeemsLikeInfinity時,都會爲該對象創建一個新的$this - 因此在實例化類時$this->instance始終爲null

那麼,什麼是發生在你的構造函數:

if ($this->instance == null) { 
    $this->instance = new self; 
} 

...是一個新的$this->instance(沒有指定的值)時,在構造對象,從而一個新的對象被創建一個新的$this->instance創建,再次沒有價值,所以一個新的對象被構​​建爲新的$this->instance,同樣沒有價值......等等,永遠。

但是,靜態變量與類本身有關......您可以隨意多次實例化類,並且創建的每個對象都將繼承類中靜態變量的最後一組值。

什麼你想要做的就是創建一個Singleton,所以你永遠不會調用構造函數直接,實例化,並通過靜態getInstance()方法訪問類:

// I've made this a "final" class - you can't really 
// extend Singletons without getting into a mess 
final class SeemsLikeInfinity { 

    // this needs to be a static variable as it'll 
    // be checked from the static self::getInstance() method 
    // it should also be private as you'll never call it from 
    // outside the class 
    private static $instance; 

    // the constructor function should also be private 
    // as it'll ONLY ever be called from the 
    // self::getInstance() method 
    private function __construct() { 
    // ... do stuff here to instantiate your class 
    } 

    // Singletons can't be cloned 
    public function __clone() { 
    throw new Exception("ERROR : you can't clone Singletons", E_USER_ERROR); 
    } 

    // this is the main getInstance() method called 
    // to actually instantiate or call the class 
    public static function getInstance() { 
    if(!self::$instance) { self::$instance = new self(); } 
    return self::$instance; 
    } 
} 

// now, to instantiate or access your class you'd use getInstance() 
// you'll no longer have permanently reiterating classes and you 
// should be golden 
$looping = SeemsLikeInfinity::getInstance(); 

順便說一句,最好用我我們發現單身人士正在建立一個會話管理包裝器,因爲會議本身就具有一個實例。