2016-07-25 92 views
1

如何解決這個問題的最佳方法?也許爲此創建了任何模式?PHP OOP內部方法調用

我有類Master,它通過DI管理一個Slave對象。類Slave的實例必須具有父內部的Master。事情是這樣的:

class Master 
{ 
    private $slave; 

    public function __construct(Slave $slave) 
    { 
    $slave->registerMaster($this); 
    $this->slave = $slave; 
    } 
} 

class Slave 
{ 
    private $master; 

    public function registerMaster(Master $master) 
    { 
    $this->master = $master; 
    } 
} 

只有類Master可以調用registerMaster方法。在這個例子中,有哪些方式可以幫助我?

+0

什麼是找你問題現在呢? – jmattheis

+0

我想禁用registerMaster外面,以便用戶不能自己做這個。 – Mati

+0

您的問題沒有意義 - 請清理並正確定義。我所看到的只是你只想讓'Master'能夠調用'registerMaster()'? – Darren

回答

2

只有班級的主人可以調用registerMaster方法。在這個例子中,有哪些方式可以幫助我?

在PHP中沒有朋友類的概念,所以沒有辦法從另一個類隱藏公共方法。

你可以使用繼承和保護的可見

abstract class LinkedEntity { 
    protected $master; 
    protected $slave;  
} 

class Master extends LinkedEntity { 
    public function __construct(Slave $slave) { 
     $this->slave = $slave; 
     $this->slave->master = $this; 
    } 
} 

class Slave extends LinkedEntity {} 

$slave = new Slave; 
$master = new Master($slave); 

由於Master和Slave現在延長相同的基類,受保護的屬性都可以訪問他們,而不是任何其他類。在LinkedEntity類中定義的受保護方法也是如此。所以你可以放一個protected registerMaster(Master $master)方法並且通過它來代替直接分配屬性。我個人覺得不那麼漂亮,我想知道你是否真的需要雙向關聯,或者是否有足夠的單向關聯性,例如,從主站到從站,或反之亦然。

另一個,甚至更壞的選擇,將是檢查調用堆棧:

class Slave { 
    private $master; 
    public function registerMaster(Master $master) 
    { 
     if (debug_backtrace(null, 2)[1]["class"] === Master::class) { 
      throw new RuntimeException("Only Masters may call Slaves"); 
     } 
     $this->master = $master; 
    } 
} 

的方法檢查調用堆棧(在一個沒有來電轉接到您registerMaster以前的類實際上是一個大師。然而,當你的方法取決於誰是被叫方是信息,它通常是設計不良的徵兆。

第三種選擇是通過通過反射奴隸的方法的可見性突破,如

class Master { 
    private $slave; 
    public function __construct(Slave $slave) { 
     $this->slave = $slave; 
     $fn = new ReflectionMethod($slave, 'registerMaster'); 
     $fn->setAccessible(true); 
     $fn->invoke($slave, $this); 
    } 
} 

class Slave { 
    private $master; 
    private function registerMaster(Master $master) 
    { 
     $this->master = $master; 
    } 
} 

同樣,這不是最優的,因爲OOP的核心原則是信息隱藏,我們在這裏打破它。我們正在突破指定的私人知名度並強制它向公衆公開。此外,這不會阻止任何其他對象執行相同的操作。

0

避免了額外的類方法中的另一種方式是閉包綁定到另一個類的私有範圍,這樣你就可以直接訪問所有的方法和屬性:

class Master 
{ 
    private $slave; 

    public function __construct(Slave $slave) 
    { 
    $this->slave = $slave; 
    $master  = $this; 
    $masterInjector = function (Master $master) { 
     $this->master = $master; 
    }; 
    $masterInjector->call($slave, $master); 
    } 
} 

class Slave 
{ 
    private $master; 
}