我知道大多数OOP语言(如果不是全部)的私有可见性在类的基础上定义隐私,即同一类的不同实例可以访问彼此的私有属性/方法。
我想阻止这一点,我想知道什么是最好的设计/实施,以便没有负面的性能影响。
例如,我知道我可以实现AOP并使用符号,但这会导致性能下降,因为languange引擎必须创建类的反射并检查注释。所以,基本上,我的问题是,避免同一个类的实例访问彼此的私有方法/属性的最佳方法是什么?
示例:
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);
答案 0 :(得分:4)
只是不要写代码来访问其他实体'私人,期间。可见性修饰符可以帮助你不会轻易拍摄自己的脚。他们不是锁和钥匙。你可以通过多种方式避免"规避" "访问保护"。只是一个负责任的成年人而不是修改属性,除非你在它之前写了$this->
。
答案 1 :(得分:1)
您也可以使用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);
答案 2 :(得分:0)
我不确定但是:
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);
答案 3 :(得分:0)
如果没有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(),但是您不能声明该字段,否则不会调用魔术方法。
答案 4 :(得分:0)
这是给定的oop行为,不仅在PHP中。 PHP手册介绍了此here。这就是您的代码,提供了此功能。