Dlaczego nie można przechwycić chronionych metod?

14

Zastanawiałem się, dlaczego nie można tworzyć wtyczek dla protectedmetod. Ten fragment kodu znajduje się w 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;
}

Sprawdza, czy metoda jest publicprzed zezwoleniem na przechwycenie. To może być łatwo zmieniona przez stworzenie preferencew di.xmlwłasnego modułu, oczywiście, jak to:

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

i przepisanie _getClassMethodsze \ReflectionMethod::IS_PUBLICzmienionym na \ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTEDwewnątrz metody.

Ale zastanawiam się, dlaczego nie jest możliwe przechwycenie chronionych metod w oryginalnej definicji metody? Czy ma to duży wpływ na wydajność, czy może ma to jakiś inny powód, na przykład pozwala innym modułom sprawić, że logika Magento będzie zbyt „nieuporządkowana”?

Bartosz Górski
źródło

Odpowiedzi:

24

Według dokumentów Magento nie można „użyć” wtyczki do chronionej metody.

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

Nie możesz zastosować wtyczek do:

  • Ostateczne metody
  • Klasy końcowe
  • Każda klasa, która zawiera co najmniej jedną ostateczną metodę publiczną
  • Metody niepubliczne
  • Metody klasowe (takie jak metody statyczne)
  • __construct Typy wirtualne

Ale masz rację, zgodnie z ___callPluginsdefinicją w Magento\Framework\Interception\Interceptor, nie widzę żadnego problemu przy użyciu chronionych metod.

Moim pierwszym przypuszczeniem jest to, że ograniczyli go, aby uniknąć dużej złożoności kodu, ponieważ Magento powinien przepisać dowolną chronioną metodę i wywołać ___callPluginskażdą z nich ... to strasznie spowolni IMHO.

Ale myślę, że prawdziwym powodem jest logiczna konsystencja: wtyczki powinny być używane do zmiany danych wyjściowych / wejściowych metod klas , a nie do przepisywania zachowania wewnętrznego, więc powinny one mieć dostęp tylko do metod publicznych.

Aby przepisać zachowanie wewnętrzne, musisz użyć preferencji. To ma sens.

Phoenix128_RiccardoT
źródło
1
Dobra odpowiedź. Zastanawiałem się nad tym również, ale z punktu widzenia OOP / SOLID sensowne jest, aby pozwalać na przechwytywanie tylko metod publicznych.
Giel Berkers,
13

Jeśli dobrze pamiętam z prezentacji Antona Krilla, powiedział, że technicznie chronione metody mogą zostać przechwycone, ale to przeczy celowi ich „ochrony”.
Klasa przechwytująca, która jest generowana automatycznie, rozszerza klasę oryginalną, dzięki czemu ma dostęp do chronionych metod.
Ale ... Metody chronione nie powinny być dostępne poza klasą.
Więc jest to bardziej decyzja niż ograniczenie.

Marius
źródło
-4

Jest to funkcja bezpieczeństwa OOPS, która nie jest specyficzna dla Magento.

Metody publiczne oznaczone przez public są dostępne dla każdej klasy. Metody chronione oznaczone jako chronione są dostępne dla podklas i klas przyjaznych, które są klasami w tym samym pakiecie. Przyjazne metody oznaczone jako nic (tj. Domyślne) są dostępne dla przyjaznych klas. Metody prywatne są dostępne tylko dla samej klasy.

Powody:

1) Metody chronione nie mogą uzyskać dostępu na drugim poziomie dziedziczenia.

przykład: Weźmy na przykład dwie klasy klasy A i klasy B w tym samym pakiecie.

Klasa B może chronić zarówno dziedziczone, jak i publiczne metody klasy A.

Sourav
źródło
4
Protected methods... which are classes in the same package- to nie jest prawda. Metody chronione są dostępne tylko dla klas dostępnych w tej samej hierarchii poprzez dziedziczenie - bez względu na to, czy są one w tym samym pakiecie, czy nie. Protected Methods can't access in Inheritence second level.- znowu nieprawda - chronione metody są dostępne na dowolnym poziomie dziedziczenia, po prostu nie spoza zakresu obiektu
Robbie Averill