Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php/OOP如何避免同一类的实例从其他对象访问私有属性/方法_Php_Oop - Fatal编程技术网

Php/OOP如何避免同一类的实例从其他对象访问私有属性/方法

Php/OOP如何避免同一类的实例从其他对象访问私有属性/方法,php,oop,Php,Oop,我知道大多数OOP语言(如果不是全部的话)中的私有可见性都以类为基础定义隐私,即同一类的不同实例可以访问彼此的私有属性/方法 我想防止这种情况发生,我想知道什么是最好的设计/实现,这样做不会对性能造成负面影响 例如,我知道我可以实现AOP并使用注释,但这会导致性能下降,因为languange引擎必须创建类的反射并检查注释。所以,基本上,我的问题是,避免同一类的实例访问彼此的私有方法/属性的最佳方法是什么 例如: class Product { private $_prize; p

我知道大多数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);

简单地说,不要编写访问其他实体隐私的代码。可见性修改器可以帮助您不太容易地射中自己的脚。它们不是锁和钥匙。您仍然可以通过多种方式“规避”访问保护。做一个负责任的成年人,不要修改属性,除非你在它前面写了一个
$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的可能性。因为他的问题是:避免同一类的实例访问彼此的私有方法/属性的最佳方法是什么?这是一个很好的答案。然而,它根本没有解决我的问题。如果我必须避免这种行为(正如我在问题中提到的),因为该类是遗留类,无法完全重构,会发生什么?我知道这个设计很糟糕,但我仍然好奇如何防止/修复/修正我上面描述的行为(如果可能的话)。