Php/OOP如何避免同一类的实例从其他对象访问私有属性/方法
我知道大多数OOP语言(如果不是全部的话)中的私有可见性都以类为基础定义隐私,即同一类的不同实例可以访问彼此的私有属性/方法 我想防止这种情况发生,我想知道什么是最好的设计/实现,这样做不会对性能造成负面影响 例如,我知道我可以实现AOP并使用注释,但这会导致性能下降,因为languange引擎必须创建类的反射并检查注释。所以,基本上,我的问题是,避免同一类的实例访问彼此的私有方法/属性的最佳方法是什么 例如:Php/OOP如何避免同一类的实例从其他对象访问私有属性/方法,php,oop,Php,Oop,我知道大多数OOP语言(如果不是全部的话)中的私有可见性都以类为基础定义隐私,即同一类的不同实例可以访问彼此的私有属性/方法 我想防止这种情况发生,我想知道什么是最好的设计/实现,这样做不会对性能造成负面影响 例如,我知道我可以实现AOP并使用注释,但这会导致性能下降,因为languange引擎必须创建类的反射并检查注释。所以,基本上,我的问题是,避免同一类的实例访问彼此的私有方法/属性的最佳方法是什么 例如: class Product { private $_prize; p
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->
。我不确定,但是:
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);
您也可以通过
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);
在没有getter和setter的情况下,根本不访问任何属性。然后在getter和setter中,通过
(debug\u backtrace(debug\u backtrace\u PROVIDE\u 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
可以替换为uuu get()和uu set(),但是您不能声明字段,否则将不会调用神奇的方法。这不仅是PHP中给定的oop行为。PHP手册对此进行了描述。这是您提供此功能的代码。如果是这样,为什么需要多个实例?我不完全理解您的问题,但它似乎会有所帮助。我也考虑过一个单例,但这意味着他只使用一个对象,这就是为什么我问他为什么需要多个实例,因为产品A有奖,但如果与产品B一起销售,则会有折扣。我相信一个包含这两种产品的Cart对象是最好的设计,但我想知道如何避免这种情况,因为为什么需要将ReflectionClass
实例从外部传递到方法中?!这是一个多么棒的方法签名。。。不过,我不太清楚这是怎么回事。为什么需要测试该财产是否为私有财产?您已经知道了,因为您声明它是这样的……因为相同类型的对象将可以访问彼此的私有和受保护成员。而不是制作$productB->\u奖品
0。这告诉你,你不能。当然,我理解。尽管如此,这个属性仍然是私有的,它在类的顶部这样说。你已经知道了。支票总是假的。为什么要写它?如果(false),您也可以编写,它同样有意义。同意,它将始终返回“是私有财产”。我只是展示了OP的可能性。因为他的问题是:避免同一类的实例访问彼此的私有方法/属性的最佳方法是什么?这是一个很好的答案。然而,它根本没有解决我的问题。如果我必须避免这种行为(正如我在问题中提到的),因为该类是遗留类,无法完全重构,会发生什么?我知道这个设计很糟糕,但我仍然好奇如何防止/修复/修正我上面描述的行为(如果可能的话)。