PHP में देर से स्थैतिक बाइंडिंग क्या हैं?


जवाबों:


198

PHP मेनुअल में आपको लेट स्टैटिक बाइंडिंग को जरूर पढ़ना चाहिए । हालाँकि, मैं आपको एक त्वरित सारांश देने की कोशिश करूँगा।

मूल रूप से, यह इस तथ्य से उबलता है कि selfकीवर्ड विरासत के समान नियमों का पालन नहीं करता है। selfहमेशा उस कक्षा में हल करता है जिसमें इसका उपयोग किया जाता है। इसका मतलब यह है कि यदि आप किसी अभिभावक वर्ग में एक विधि बनाते हैं और उसे बच्चे की कक्षा से बुलाते हैं, selfतो बच्चे का संदर्भ नहीं देंगे जैसा कि आप उम्मीद कर सकते हैं।

लेट स्टैटिक बाइंडिंग staticकीवर्ड के लिए एक नया प्रयोग प्रस्तुत करता है, जो इस विशेष कमी को संबोधित करता है। जब आप उपयोग staticकरते हैं , तो यह उस वर्ग का प्रतिनिधित्व करता है जहां आप पहली बार इसका उपयोग करते हैं, अर्थात। यह रनटाइम क्लास को 'बांधता' है।

इसके पीछे दो बुनियादी अवधारणाएँ हैं। जिस तरह से self, parentऔर staticजब staticखेल में होता है, तब काम किया जा सकता है, इसलिए इसे और अधिक विस्तार से जाने के बजाय, मैं दृढ़ता से अनुशंसा करूंगा कि आप मैनुअल वीडियो उदाहरणों का अध्ययन करें। एक बार जब आप प्रत्येक कीवर्ड की मूल बातें समझ लेते हैं, तो उदाहरण देखने के लिए बहुत आवश्यक होते हैं कि आपको किस प्रकार के परिणाम मिलने वाले हैं।


मैं, इस लेख वास्तव में उपयोगी और वर्णनात्मक पाया और उसे देखें [कड़ी] ( techflirt.com/tutorials/oop-in-php/late-static-binding.html )
सादेग Shaikhi

"... selfकीवर्ड वंशानुक्रम के नियमों का पालन नहीं करता है। selfहमेशा उस वर्ग का समाधान करता है जिसमें इसका उपयोग किया जाता है।" - इसका मतलब यह नहीं है कि आप किसी selfगैर-स्टैटिक विधियों की तरह, किसी चाइल्ड ऑब्जेक्ट से माता-पिता की स्टेटिक विधि को नहीं कह सकते । आप शायद सही बात का मतलब है, लेकिन आप फिर से वाक्यांश होना चाहिए। यह सब वास्तव में केवल एक बार मायने रखता है जब बच्चों ने पहचान के सदस्यों का नाम लिया है क्योंकि आप तब यह तय कर सकते हैं कि किन लोगों को static::इसके बजाय उपयोग करना है।
डैनमैन

81

से पीएचपी: स्वर्गीय स्टेटिक बाइंडिंग - मैनुअल :

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
?>

देर से स्थिर बाइंडिंग अंतिम "गैर-अग्रेषण कॉल" नाम के वर्ग को संग्रहीत करके काम करता है। स्थैतिक विधि कॉल के मामले में, यह स्पष्ट रूप से नामित वर्ग है (आमतौर पर ::ऑपरेटर के बाईं ओर ); गैर-स्थैतिक विधि कॉल के मामले में, यह ऑब्जेक्ट का वर्ग है। एक "अग्रेषण कॉल" एक स्थिर एक है कि द्वारा शुरू की गई है self::, parent::, static::, या, यदि वर्ग पदानुक्रम में ऊपर जा रहा है, forward_static_call()। फ़ंक्शन get_called_class()का उपयोग बुलाए गए वर्ग के नाम के साथ एक स्ट्रिंग को पुनः प्राप्त करने के लिए किया जा सकता है और static::इसके दायरे का परिचय दे सकता है।


1
यह पोस्ट ~ 80% है, उद्धरण चिह्नों के बिना php.net लेख की एक शब्दशः कॉपी ।
वुड्रोशाइगरु

22

बहुत स्पष्ट व्यवहार नहीं है:

निम्नलिखित कोड 'अल्फ़ाबेटा' का निर्माण करता है।

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

हालांकि, यदि हम बीटा वर्ग से क्लासनाम फ़ंक्शन की घोषणा को हटाते हैं, तो हमें परिणाम के रूप में 'अल्फ़ाल्फा' मिलता है।


1
बहुत अच्छा। PHP मैनुअल में भी यही बात दिखाई जाती है, लेकिन यह बहुत स्पष्ट है। संदर्भ के लिए: php.net/manual/en/language.oop5.late-static-bindings.php (देखें एक्स। 4)
musicin3d

11

मैं पुस्तक से उद्धृत कर रहा हूँ: "PHP मास्टर अत्याधुनिक लेखन"।

लेट स्टैटिक बाइंडिंग 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

चाइल्ड क्लास 2 तरीकों से आगे निकल जाता है:

  • 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कीवर्ड एक सिंगलटन डिजाइन पैटर्न में प्रयोग किया जाता है। लिंक देखें: https://refactoring.guru/design-patterns/singleton/php/example


7

अंतर दिखाने के लिए सबसे सरल उदाहरण।
नोट, स्व :: $ 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

4

उदाहरण के लिए:

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();

4

इसे "मैं इसका उपयोग क्यों करूंगा?" परिप्रेक्ष्य, यह मूल रूप से संदर्भ को बदलने का एक तरीका है जिसमें से स्थिर विधि की व्याख्या / रन किया जा रहा है।

के साथ self, संदर्भ वह है जहां आपने विधि को मूल रूप से परिभाषित किया है। इसके साथ static, यह वह है जिससे आप इसे कॉल कर रहे हैं।


1

यह भी देखें कि क्या आप बाल कक्षाओं में स्थिर चर अद्यतन करते हैं। मुझे यह (कुछ) अप्रत्याशित परिणाम मिला जहां बच्चा बी बच्चे को सी अपडेट करता है:

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;        
    }
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.