Php 如何从库类重写私有方法

Php 如何从库类重写私有方法,php,overriding,private,Php,Overriding,Private,下面给出了类A来自的类,因此我无法更改它: class A { public function test () { $this->privateMethod(); } private function privateMethod () { echo('A'); } } class B extends A { private function privateMethod () { echo('B');

下面给出了类
A
来自的类,因此我无法更改它:

class A {
    public function test () {
        $this->privateMethod();
    }
    private function privateMethod () {
        echo('A');
    }
}

class B extends A {
    private function privateMethod () {
        echo('B');
    }
}

$b = new B();
$b->test();
这导致
A
A::privateMethod
而不是
B::privateMethod
打印出来,因为后者对
A::test
不可见


否则,我如何才能以最干净的方式修改此私有库方法的行为(例如,复制整个类并对其进行更改时不会出现代码重复)?

这是因为
private
仅在类本身的范围内。如果您使用了
protected
,您会重写该函数,因为
protected
方法意味着它可用于子类。

您可以使用以下方法更改类方法的可访问性:


考虑到此代码将是“脆弱的”,因为库的作者不会考虑库的用户依赖于私有函数的结果。自己复制函数的代码可能比搞乱库本身要好。

您可以间接操纵行为。这是您感兴趣的代码片段

$allCss = $this->css;

if ($this->isStyleBlocksParsingEnabled) {
    $allCss .= $this->getCssFromAllStyleNodes($xpath);
}
查看类设置器,您可以调用
disablestyleblocksparing
来防止调用该函数

$allCss
变量直接取自
$this->css
,该变量仅由
setCss
方法修改

所以你有两个选择:

  • 扩展该类,使
    IsStyleBlocksParSingabled
    false和immutable,然后重写
    setCss
    方法以执行您想要执行的
    getCssFromAllStyleNodes
    操作
  • 调用
    disablestyleblocksparing
    并使用预处理文本调用
    setCss
以下是第一个选项的示例:

class MyEmogrifier extends Emogrifier
{
    public function __construct($html = '', $css = '')
    {
        parent::__construct($html, $css);

        $this->disableStyleBlocksParsing();
    }

    public function setCss($css)
    {
        // Preprocess CSS here.

        parent::setCss($css);
    }
}
因此,不需要进行枪战手术,也不需要进行反思


不过说实话。我甚至不太愿意使用像这样一个具体的图书馆。我几乎所有的私有方法都使用
受保护的

您可以通过 这是它的一部分

将属性设置为可访问。例如,它可能允许受保护的 以及要访问的私有属性


这是危险的但在某些情况下,您可以使用它。

有几种解决方案,如果您使用的是开源库,了解您使用的库可能会很有用。是的。我需要更改
getCssFromAllStyleNodes
。我知道它为什么不起作用,但我正在寻找一种不同的方法来实现我在问题中所述的目标。在库类中将
private
更改为
protected
。它不会影响库中使用的任何代码,但它允许您重写它。我认为这并不能回答问题。OP说这是一个库,所以他不能更改访问修饰符。如果它不能更改,你就不能。
class MyEmogrifier extends Emogrifier
{
    public function __construct($html = '', $css = '')
    {
        parent::__construct($html, $css);

        $this->disableStyleBlocksParsing();
    }

    public function setCss($css)
    {
        // Preprocess CSS here.

        parent::setCss($css);
    }
}