Pourquoi les méthodes protégées ne peuvent pas être interceptées?

14

Je me demandais pourquoi il n'était pas possible de créer des plugins pour les protectedméthodes. Il y a ce morceau de code dans 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;
}

Il vérifie si la méthode est publicavant de permettre son interception. Il peut être facilement modifié en créant un preferencedans le di.xmlpropre module, bien sûr, comme ceci:

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

et réécriture du _getClassMethodsavec le \ReflectionMethod::IS_PUBLICchangé à l' \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTEDintérieur de la méthode.

Mais je me demande pourquoi il n'est pas possible d'intercepter des méthodes protégées dans la définition de méthode d'origine? Cela a-t-il un impact majeur sur les performances, ou il y a une autre raison à cela, comme autoriser des modules tiers à rendre la logique de Magento trop "désordonnée"?

Bartosz Górski
la source

Réponses:

24

Selon les documents de Magento, il n'est pas "possible" d'utiliser un plugin sur une méthode protégée.

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

Vous ne pouvez pas appliquer de plugins à:

  • Méthodes finales
  • Classes finales
  • Toute classe contenant au moins une méthode publique finale
  • Méthodes non publiques
  • Méthodes de classe (telles que les méthodes statiques)
  • __construct types virtuels

Mais votre point est correct, selon la ___callPluginsdéfinition de Magento\Framework\Interception\Interceptor, je ne vois aucun problème à utiliser des méthodes protégées.

Ma première supposition est qu'ils l'ont limité pour éviter une complexité de code élevée puisque Magento devrait réécrire toute méthode protégée et appeler ___callPluginspour chacun d'eux ... cela ralentira terriblement à mon humble avis.

Mais je pense que la vraie raison est d'une cohérence logique: les plugins doivent être utilisés pour changer la sortie / entrée des méthodes de classe , pas pour réécrire le comportement interne, ils ne doivent donc accéder qu'aux méthodes publiques.

Pour réécrire un comportement interne, vous devez utiliser une préférence. Ca a du sens.

Phoenix128_RiccardoT
la source
1
Bonne réponse. Je me posais également la question, mais d'un point de vue POO / SOLIDE, il est logique de ne permettre que les méthodes publiques à intercepter.
Giel Berkers
13

Si je me souviens bien d'une présentation d'Anton Krill, il a dit que les méthodes techniquement protégées peuvent être interceptées, mais cela va à l'encontre du but de les avoir "protégées".
La classe d'intercepteur générée automatiquement étend la classe d'origine afin qu'elle ait accès aux méthodes protégées.
Mais ... Les méthodes protégées ne devraient pas être disponibles en dehors de la classe.
Il s'agit donc plus d'une décision que d'une limitation.

Marius
la source
-4

Il s'agit d'une fonction de sécurité OOPS qui n'est pas spécifique à magento.

Les méthodes publiques, étiquetées par public, sont disponibles pour chaque classe. Les méthodes protégées, étiquetées par protected, sont disponibles pour les sous-classes et les classes amies, qui sont des classes dans le même package. Les méthodes amies, étiquetées par rien (c'est-à-dire par défaut) sont disponibles pour les classes amies. Les méthodes privées ne sont disponibles que pour la classe elle-même.

Les raisons:

1) Les méthodes protégées ne peuvent pas accéder au deuxième niveau d'héritage.

exemple: Prenons un exemple de deux classes Classe A & Classe B dans le même package.

La classe B ne peut être héritée que par des méthodes publiques de classe A.

Sourav
la source
4
Protected methods... which are classes in the same package- ce n'est pas vrai. Les méthodes protégées ne sont disponibles que pour les classes disponibles dans la même hiérarchie via l'héritage - qu'elles soient ou non dans le même package ne fait aucune différence. Protected Methods can't access in Inheritence second level.- encore une fois, ce n'est pas vrai - les méthodes protégées sont disponibles à tous les niveaux d'héritage, mais pas en dehors de la portée de l'objet
Robbie Averill