Как переопределить приватный метод из библиотечного класса

Даны следующие классы с классом 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 от B::privateMethodпотому что последний не виден A::test как объяснили Вот.

Как еще можно изменить поведение этого метода частной библиотеки самым чистым способом (например, без дублирования кода путем копирования всего класса и его изменения)?

0

Решение

Вы можете манипулировать поведением косвенно. Это фрагмент, который вас интересует.

$allCss = $this->css;

if ($this->isStyleBlocksParsingEnabled) {
$allCss .= $this->getCssFromAllStyleNodes($xpath);
}

Глядя на установщиков классов, вы можете позвонить disableStyleBlocksParsing чтобы предотвратить вызов функции.

$allCss переменная берется прямо из $this->css, который изменяется только setCss метод.

Итак, у вас есть два варианта:

  • Расширьте класс, сделайте isStyleBlocksParsingEnabled ложный и неизменный, затем переопределить setCss способ сделать то, что вы хотели getCssFromAllStyleNodes сделать.
  • Вызов disableStyleBlocksParsing и позвони 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);
}
}

Таким образом, нет никакой операции с дробовиком или рефлексии.

Если честно, хотя. Я бы чувствовал себя гораздо менее склонным даже использовать такую ​​конкретную библиотеку, как эта. я использую protected почти все мои были бы частными методами.

1

Другие решения

Это потому private находится только в сфере действия самого класса. Я тебя использовал protected вы бы переопределили функцию, потому что protected Метод означает, что он доступен для дочерних классов.

4

Вы можете изменить доступность метода класса, используя ReflectionMethod::setAccessible():

$myEmogrifier = new \Pelago\Emogrifier;
$reflectedMethod = new ReflectionMethod($myEmogrifier, 'getCssFromAllStyleNodes');
$reflectedMethod->setAccessible(true);
$argument = new \DOMXpath(new \DOMDocument);
$returnValue = $reflectedMethod->invoke($myEmogrifier, $argument);

Примите во внимание, что этот код будет «хрупким», поскольку автор библиотеки не будет учитывать, что пользователь библиотеки полагается на результат частной функции. Может быть, лучше просто продублировать код функции самостоятельно, чем возиться с самой библиотекой.

1

Вы можете изменить жесткий код visibility собственности через ReflectionClass :: setAccessible
это часть ReflectionClass.

Устанавливает свойство, которое будет доступно. Например, это может позволить
и частные свойства, которые будут доступны.

Это опасно но в некоторых случаях вы можете использовать его.

0
По вопросам рекламы [email protected]