Почему защищенные методы не могут быть перехвачены?

14

Мне было интересно, почему невозможно создать плагины для protectedметодов. Этот фрагмент кода есть в Magento\Framework\Interception\Code\Generator\Interceptor:

protected function _getClassMethods()
{
    $methods = [$this->_getDefaultConstructorDefinition()];

    $reflectionClass = new \ReflectionClass($this->getSourceClassName());
    $publicMethods = $reflectionClass->getMethods(\ReflectionMethod::IS_PUBLIC);
    foreach ($publicMethods as $method) {
        if ($this->isInterceptedMethod($method)) {
            $methods[] = $this->_getMethodInfo($method);
        }
    }
    return $methods;
}

Он проверяет, есть ли метод, publicпрежде чем разрешить его перехват. Это может быть легко изменено путем создания preferenceв di.xmlсобственном модуле, конечно, так:

<?xml version="1.0"?>
<config>
    <preference for="Magento\Framework\Interception\Code\Generator\Interceptor" type="MyVendor\MyModule\Model\MyInterceptorModel" />
</config>

и переписать _getClassMethodsс \ReflectionMethod::IS_PUBLICизмененным \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTEDвнутри метода.

Но мне интересно, почему невозможно перехватить защищенные методы в исходном определении метода? Влияет ли это на производительность или есть какая-то другая причина, например, позволяющая сторонним модулям делать логику Magento слишком «грязной»?

Бартош Гурски
источник

Ответы:

24

Согласно Magento docs, использование плагина для защищенного метода «невозможно».

( http://devdocs.magento.com/guides/v2.0/extension-dev-guide/plugins.html )

Вы не можете применять плагины к:

  • Финальные методы
  • Выпускные занятия
  • Любой класс, который содержит хотя бы один последний публичный метод
  • Непубличные методы
  • Методы класса (такие как статические методы)
  • __construct Виртуальные типы

Но ваша точка зрения верна, согласно ___callPluginsопределению Magento\Framework\Interception\Interceptor, я не вижу проблем с использованием защищенных методов.

Мое первое предположение состоит в том, что они ограничили его, чтобы избежать высокой сложности кода, поскольку Magento должен переписать любой защищенный метод и вызвать ___callPluginsдля каждого из них ... это ужасно замедлит ИМХО.

Но я думаю, что настоящая причина заключается в логическом согласии: плагины должны использоваться для изменения методов вывода / ввода класса , а не для переписывания внутреннего поведения, поэтому они должны иметь доступ только к открытым методам.

Чтобы переписать внутреннее поведение, вы должны использовать предпочтения. Это имеет смысл.

Phoenix128_RiccardoT
источник
1
Хороший ответ. Мне тоже было интересно, но с точки зрения OOP / SOLID имеет смысл разрешать перехват только публичных методов.
Giel Berkers
13

Если я правильно помню из выступления Антона Криля, он сказал, что технически защищенные методы могут быть перехвачены, но это противоречит цели их "защиты".
Класс перехватчика, который создается автоматически, расширяет исходный класс, поэтому у него есть доступ к защищенным методам.
Но ... Защищенные методы не должны быть доступны вне класса.
Так что это скорее решение, чем ограничение.

Мариус
источник
-4

Это функция безопасности OOPS, не зависящая от magento.

Публичные методы, помеченные как public, доступны для каждого класса. Защищенные методы, помеченные защищенными, доступны для подклассов и дружественных классов, которые являются классами в одном пакете. Дружественные методы, помеченные ничем (то есть по умолчанию), доступны для дружественных классов. Приватные методы доступны только самому классу.

Причины:

1) Защищенные методы не могут получить доступ на втором уровне наследования.

пример: давайте возьмем для примера два класса Class A и Class B в одном пакете.

Класс B может защищать только наследование, а также общедоступные методы класса A.

Sourav
источник
4
Protected methods... which are classes in the same package- это неправда. Защищенные методы доступны только для классов, доступных в одной иерархии через наследование - независимо от того, находятся они в одном пакете или нет, не имеет значения. Protected Methods can't access in Inheritence second level.- опять же, это не так - защищенные методы доступны на любом уровне наследования, но только за пределами области видимости объекта
Робби Аверилл,