![](/img/trans.png)
[英]Visibility of Protected/Private Properties from Other Instances of Same Class
[英]Php/OOP How to avoid instances of the same class to access private properties/methods from other objects
我知道大多數 OOP 語言(如果不是全部)中的私有可見性以類為基礎定義隱私,即同一類的不同實例可以訪問彼此的私有屬性/方法。
我想防止這種情況發生,我想知道什么是最好的設計/實現,以便在不產生負面性能影響的情況下做到這一點。
例如,我知道我可以實現 AOP 並使用符號,但這會導致性能下降,因為語言引擎必須創建類的反射並檢查注釋。 所以,基本上,我的問題是,避免同一類的實例訪問彼此的私有方法/屬性的最佳方法是什么?
例子:
class Product
{
private $_prize;
public function __construct($prize)
{
$this->_prize = $prize;
}
public function calculateDiscount(Product $extraProduct)
{
$extraProduct->_prize = 0; //How to avoid this?
}
}
$productA = new Product(10);
$productB = new Product(25);
$productA->calculateDiscount($productB);
只是不要編寫訪問其他實體私有的代碼,句號。 能見度調節器可幫助您不至於輕易射中自己的腳。 它們不是鎖和鑰匙。 您仍然可以通過多種方式“規避”“訪問保護”。 做一個負責任的成年人,不要修改屬性,除非你在它之前寫了一個$this->
。
您也可以使用ReflectionClass
實現此目的
class Product
{
private $_prize;
public function __construct($prize)
{
$this->_prize = $prize;
}
public function calculateDiscount(Product $extraProduct)
{
if(!(new ReflectionClass($extraProduct))->getProperty('_prize')->isPrivate()){
$extraProduct->_prize = 0; //How to avoid this?
} else {
echo "Is private property";
}
}
}
$productA = new Product(10);
$productB = new Product(25);
$productA->calculateDiscount($productB);
我不確定但是:
class Product
{
private $_prize;
public function __construct($prize)
{
$this->_prize = $prize;
}
public function calculateDiscount(Product $extraProduct)
{
$extraProduct->setPrize(0);
}
public function setPrize( $v ) {
$this->_prize = $v;
}
}
$productA = new Product(10);
$productB = new Product(25);
$productA->calculateDiscount($productB);
在沒有 getter 和 setter 的情況下,根本不要訪問任何屬性。 然后在你的 getter 和 setter 中,通過(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT)[0]["object"] ?? null) === $this
檢查調用上下文是否是同一個類。
例如:
class Foo{
private $bar;
public function getBar(){
return $this->bar;
}
private function setBar($bar){
self::assertCalledByThis();
$this->bar = $bar;
}
private static function assertCalledByThis(){
$trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS);
$fromObject = $trace[1]["object"] ?? null; // context calling setBar()
$toObject = $trace[0]["object"] ?? null; // context calling assertCalledByThis()
assert($fromObject === $toObject);
}
}
當然,你的getBar
和setBar
可以用 __get() 和 __set() 代替,但是你一定不能聲明字段,否則魔法方法不會被調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.