سؤال

ما هي بالضبط الربائح الثابتة المتأخرة في فب؟

هل كانت مفيدة؟

المحلول

تحتاج بالتأكيد إلى القراءة الروابط الثابتة المتأخرة في دليل PHP. ومع ذلك، سأحاول أن أعطيك ملخص سريع.

أساسا، يغلي إلى حقيقة أن self الكلمة الرئيسية لا تتبع نفس القواعد المتمثلة في الميراث. self دائما يحل إلى الفصل الذي يتم فيه استخدامه. هذا يعني أنه إذا قمت بإجراء طريقة في فئة الوالدين واتصل بها من فئة طفل، self لن أشير إلى الطفل كما قد تتوقع.

ربط ثابت ثابت يقدم استخدام جديد ل static الكلمة الرئيسية التي تعالج هذا القصور المحدد. عند استخدامها static, ، إنه يمثل الفصل الذي تستخدمه لأول مرة، أي. انها "يرتبط" إلى فئة وقت التشغيل.

هذه هي المفاهيم الأساسية وراءها. الطريقة self, parent و static تعمل متى static في اللعب يمكن أن يكون دقيقا، لذا بدلا من الذهاب إلى مزيد من التفاصيل، أوصي بشدة بدراسة أمثلة الصفحة اليدوية. بمجرد فهم أساسيات كل كلمة رئيسية، تكون الأمثلة ضرورية للغاية لمعرفة نوع النتائج التي ستحصل عليها.

نصائح أخرى

اعتبارا من PHP 5.3.0، ينفذ PHP ميزة تسمى الربط الثابت المتأخر يمكن استخدامها للإشارة إلى الفئة المسماة في سياق الميراث الثابت.

يحاول ربط التوصيل الثابت المتأخر حل هذا القيد من خلال إدخال الكلمة الرئيسية التي تشير إلى الفئة التي تم استدعاؤها في البداية في وقت التشغيل. تقرر عدم تقديم كلمة رئيسية جديدة، ولكن استخدامها static التي كانت محفوظة بالفعل.

دعونا نرى مثالا:

<?php
    class Car
    {
        public static function run()
        {
            return static::getName();
        }

        private static function getName()
        {
            return 'Car';
        }
    }

    class Toyota extends Car
    {
        public static function getName()
        {
            return 'Toyota';
        }
    }

    echo Car::run(); // Output: Car
    echo Toyota::run(); // Output: Toyota
?>

late static bindings العمل عن طريق تخزين الفئة المسماة في آخر "مكالمة غير إعادة التوجيه". في حالة مكالمات الأسلوب الثابت، هذا هو الفئة المسماة صراحة (عادة ما يتم ذلك على يسار :: المشغل)؛ في حالة مكالمات الطريقة غير الثابتة، فإن فئة الكائن.

"إعادة توجيه المكالمة" هي واحدة ثابتة يتم تقديمها بواسطة self::, parent::, static::, ، أو، إذا ارتفع في التسلسل الهرمي للفئة، forward_static_call().

الوظيفة get_called_class() يمكن استخدامها لاسترداد سلسلة باسم الطبقة المسمى و static:: يقدم نطاقها.

ليس هناك سلوك واضح للغاية:

ينتج التعليمات البرمجية التالية "Alphabeta".

class alpha {

    function classname(){
        return __CLASS__;
    }

    function selfname(){
        return self::classname();
    }

    function staticname(){
        return static::classname();
    }
}

class beta extends alpha {

    function classname(){
        return __CLASS__;
    }
}

$beta = new beta();
echo $beta->selfname(); // Output: alpha
echo $beta->staticname(); // Output: beta

ومع ذلك، إذا قمنا بإزالة إعلان وظيفة ClassName من فئة بيتا، نحصل على "Alphalpha" نتيجة لذلك.

اقتبس من الكتاب: "PHP Master اكتب رمز متطور".

كانت الربط الثابت المتأخر ميزة قدمت مع PHP 5.3. إنه يتيح لنا أن يرث الأساليب الثابتة من فئة الوالدين، والإشارة إلى الطبقة الفرعية التي يتم استدعاؤها.

هذا يعني أنه يمكنك الحصول على فئة مجردة مع أساليب ثابتة، والرجوع إلى التطبيقات الخرسانية لفئة الطفل باستخدام ساكنة :: الطريقة () تدوين بدلا من الذات: الطريقة ().

لا تتردد في إلقاء نظرة على وثائق PHP الرسمية كذلك:http://php.net/manual/en/language.oop5.late-static-bindings.php.


إن أوضح طريقة لشرح الربط الثابت المتأخر هو مثال بسيط. نلقي نظرة على تعريفتين الطبقة أدناه، وقراءة.

class Vehicle {
    public static function invokeDriveByStatic() {
        return static::drive(); // Late Static Binding
    }
    public static function invokeStopBySelf() {
        return self::stop(); // NOT Late Static Binding
    }
    private static function drive(){
        return "I'm driving a vehicle";
    }
    private static function stop(){
        return "I'm stopping a vehicle";
    }
}

class Car extends Vehicle  {
    protected static function drive(){
        return "I'm driving a CAR";
    }
    private static function stop(){
        return "I'm stopping a CAR";
    }
}

نرى فئة الوالدين (مركبة) وفئة طفل (سيارة). يحتوي الفصل الأصل على 2 طرق عامة:

  • invokeDriveByStatic
  • invokeStopBySelf

يحتوي الطبقة الأصل أيضا على 2 طرق خاصة:

  • drive
  • stop

تتجاوز فئة الطفل طريقتين:

  • drive
  • stop

الآن دعونا استدعاء الأساليب العامة:

  • invokeDriveByStatic
  • invokeStopBySelf

اسأل نفسك: أي فئة تدهور invokeDriveByStatic / invokeStopBySelfب الوالد أو فئة الطفل؟

نلقي نظرة أدناه:

// This is NOT Late Static Binding
// Parent class invokes from Parent. In this case Vehicle.
echo Vehicle::invokeDriveByStatic(); // I'm driving a vehicle
echo Vehicle::invokeStopBySelf(); // I'm stopping a vehicle

// This is Late Static Binding.
// Child class invokes an inherited method from Parent.
// Child class = Car, Inherited method = invokeDriveByStatic().
// ...
// The inherited method invokes a method that is overridden by the Child class.
// Overridden method = drive()
echo Car::invokeDriveByStatic(); // I'm driving a CAR

// This is NOT Late Static Binding
// Child class invokes an inherited method from Parent.
// The inherited method invokes a method inside the Vehicle context.
echo Car::invokeStopBySelf(); // I'm stopping a vehicle

ال static يتم استخدام الكلمة الأساسية في نمط تصميم Singleton. انظر الرابط: https://refactoring.guru/design-patterns/singleton/php/example.

أبسط مثال لإظهار الفرق.
ملحوظة، النفس :: $ c

class A
{
    static $c = 7;

    public static function getVal()
    {
        return self::$c;
    }
}

class B extends A
{
    static $c = 8;
}

B::getVal(); // 7

التجليد الثابت المتأخر، لاحظ ساكنة :: $ c

class A
{
    static $c = 7;

    public static function getVal()
    {
        return static::$c;
    }
}

class B extends A
{
    static $c = 8;
}

B::getVal(); // 8

علي سبيل المثال:

abstract class Builder {
    public static function build() {
        return new static;
    }
}

class Member extends Builder {
    public function who_am_i() {
         echo 'Member';
    }
}

Member::build()->who_am_i();

هل ينظر إليها من "لماذا أستخدم هذا؟" منظور، إنها طريقة لتغيير السياق الذي يتم فيه تفسير / تشغيل الطريقة الثابتة.

مع self, ، السياق هو واحد حيث حددت الطريقة في الأصل. مع static, ، إنه الشخص الذي تتصل به.

أيضا، شاهد إذا قمت بتحديث المتغيرات الثابتة في فصول الأطفال. لقد وجدت هذه نتيجة غير متوقعة (إلى حد ما) حيث يقوم الطفل ب بتحديث الطفل C:

class A{
    protected static $things;
}

class B extends A {
    public static function things(){
        static::$things[1] = 'Thing B';
        return static::$things; 
    }
}

class C extends A{
    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}

print_r(C::things());
// Array (
//   [2] => Thing C
// )

B::things();

print_r(C::things()); 
// Array (
//    [2] => Thing C
//    [1] => Thing B
// )

يمكنك إصلاحه بإعلان نفس المتغير في كل فئة طفل، على سبيل المثال:

class C extends A{
    protected static $things; // add this and B will not interfere!

    public static function things(){
        static::$things[2] = 'Thing C';
        return static::$things;        
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top