ทำไมวิธีการป้องกันที่ไม่สามารถดักจับได้?


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ภายในของวิธีการ

แต่ฉันสงสัยว่าทำไมมันเป็นไปไม่ได้ที่จะสกัดกั้นวิธีการป้องกันในคำนิยามวิธีการเดิม? มันมีผลกระทบสำคัญกับประสิทธิภาพหรือมีเหตุผลอื่น ๆ เช่นการอนุญาตให้โมดูลของบุคคลที่สามสร้างตรรกะของวีโอไอพีด้วยเช่นกัน "ยุ่ง"?

คำตอบ:


24

เอกสารของวีโอไอพีระบุว่าเป็นไปไม่ได้ที่จะใช้ปลั๊กอินในวิธีการที่ได้รับการป้องกัน

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

คุณไม่สามารถใช้ปลั๊กอินกับ:

  • วิธีการขั้นสุดท้าย
  • ชั้นเรียนสุดท้าย
  • คลาสใด ๆ ที่มีวิธีสาธารณะขั้นสุดท้ายอย่างน้อยหนึ่งวิธี
  • วิธีการที่ไม่ใช่แบบสาธารณะ
  • วิธีการเรียน (เช่นวิธีการคงที่)
  • __ สร้างประเภทเสมือน

แต่ประเด็นของคุณถูกต้องตาม___callPluginsคำนิยามในMagento\Framework\Interception\Interceptorฉันไม่เห็นปัญหาใด ๆ โดยใช้วิธีการป้องกัน

การเดาครั้งแรกของฉันคือพวกเขา จำกัด ไว้เพื่อหลีกเลี่ยงความซับซ้อนของรหัสสูงเนื่องจาก Magento ควรเขียนวิธีการป้องกันและเรียกร้อง___callPluginsให้แต่ละคน ... มันจะชะลอตัวลงอย่างรุนแรง IMHO

แต่ฉันคิดว่าเหตุผลที่แท้จริงสำหรับความสอดคล้องทางตรรกะ: ปลั๊กอินควรใช้เพื่อเปลี่ยนวิธีการเรียนการส่งออก / อินพุตไม่ได้เขียนพฤติกรรมภายในดังนั้นพวกเขาควรจะเข้าถึงวิธีการสาธารณะเท่านั้น

เพื่อเขียนพฤติกรรมภายในคุณต้องใช้การตั้งค่า มันสมเหตุสมผลแล้ว


1
คำตอบที่ดี. ฉันสงสัยตัวเองเช่นกัน แต่จากมุมมองของ OOP / SOLID มันสมเหตุสมผลที่จะอนุญาตให้มีการดักจับวิธีการสาธารณะเท่านั้น
Giel Berkers

13

ถ้าฉันจำได้อย่างถูกต้องจากการนำเสนอของ Anton Krill เขากล่าวว่าวิธีการป้องกันทางเทคนิคสามารถดักจับได้
คลาส interceptor ที่สร้างอัตโนมัติขยายคลาสดั้งเดิมเพื่อให้สามารถเข้าถึงวิธีการป้องกัน
แต่ ... วิธีการป้องกันไม่ควรมีนอกชั้นเรียน
ดังนั้นมันจึงเป็นการตัดสินใจมากกว่าข้อ จำกัด


-4

มันเป็นคุณสมบัติความปลอดภัย OOPS ไม่ใช่วีโอไอพีที่เฉพาะเจาะจง

วิธีการสาธารณะที่ติดป้ายโดยสาธารณะมีให้ทุกชั้นเรียน วิธีการป้องกันการติดฉลากโดยการป้องกันที่มีให้กับคลาสย่อยและชั้นเรียนที่เป็นมิตรซึ่งเป็นชั้นเรียนในแพคเกจเดียวกัน เมธอดที่เป็นมิตรซึ่งไม่มีป้ายกำกับ วิธีการส่วนตัวมีให้เฉพาะในชั้นเรียนเท่านั้น

เหตุผล:

1) วิธีการป้องกันไม่สามารถเข้าถึงได้ในระดับที่สองโดยสืบทอด

ตัวอย่าง: ลองดูตัวอย่างสองคลาส Class A & Class B ในแพ็คเกจเดียวกัน

คลาส B สามารถป้องกันการสืบทอดได้เป็นอย่างดีรวมถึงวิธีสาธารณะของคลาส A เท่านั้น


4
Protected methods... which are classes in the same package- นี่ไม่เป็นความจริง. วิธีที่ได้รับการป้องกันจะมีให้เฉพาะคลาสที่มีอยู่ในลำดับชั้นเดียวกันผ่านการสืบทอดไม่ว่าจะอยู่ในแพ็คเกจเดียวกันหรือไม่สร้างความแตกต่าง Protected Methods can't access in Inheritence second level.- อีกครั้งไม่เป็นความจริง - วิธีการที่ได้รับการปกป้องมีให้ในทุกระดับของการสืบทอดไม่ใช่แค่จากนอกขอบเขตของวัตถุ
Robbie Averill
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.