PHP में self :: $ bar और static :: $ bar के बीच क्या अंतर है?


125

का उपयोग करते हुए बीच क्या अंतर है selfऔर staticनीचे दिए गए उदाहरण में?

class Foo
{
    protected static $bar = 1234;

    public static function instance()
    {
        echo self::$bar;
        echo "\n";
        echo static::$bar;
    }

}

Foo::instance();

पैदा करता है

1234
1234

2
@ डिसेज़: यह एक समान प्रश्न है, लेकिन यह डुप्लिकेट नहीं है। यह एक कीवर्ड को गुणों के साथ उपयोग करने के बारे में पूछता है, जबकि वह उन्हें निर्माणकर्ताओं के साथ उपयोग करने के बारे में पूछता है।
BoltClock

जवाबों:


191

जब आप selfएक वर्ग के सदस्य को संदर्भित करने के लिए उपयोग करते हैं, तो आप उस वर्ग का उल्लेख कर रहे हैं जिसके भीतर आप कीवर्ड का उपयोग करते हैं। इस स्थिति में, आपकी Fooकक्षा एक संरक्षित स्थैतिक संपत्ति कहलाती है $bar। जब आप संपत्ति का उल्लेख करने के selfलिए Fooकक्षा में उपयोग करते हैं, तो आप उसी वर्ग को संदर्भित कर रहे हैं।

इसलिए यदि आपने self::$barअपनी Fooकक्षा में कहीं और उपयोग करने की कोशिश की है, लेकिन आपके पास Barसंपत्ति के लिए एक अलग मूल्य के साथ एक वर्ग है, तो Foo::$barइसके बजाय इसका उपयोग किया जाएगा Bar::$bar, जो कि आप जो चाहते हैं वह नहीं हो सकता है:

class Foo
{
    protected static $bar = 1234;
}

class Bar extends Foo
{
    protected static $bar = 4321;
}

जब आप किसी विधि को कॉलstatic करते हैं, तो आप लेट स्टैटिक बाइंडिंग (PHP 5.3 में प्रस्तुत) नामक एक सुविधा का आह्वान करते हैं ।

उपरोक्त परिदृश्य में, उपयोग करने के selfपरिणामस्वरूप Foo::$bar(1234) होगा। और (4321) का उपयोग करने के staticपरिणामस्वरूप , दुभाषिया रनटाइम के दौरान वर्ग के भीतर पुनर्वितरण को ध्यान में रखता है।Bar::$barstaticBar

आप आमतौर पर संपत्तियों के बजाय तरीकों या यहां तक ​​कि स्वयं वर्ग के लिए देर से स्थैतिक बाइंडिंग का उपयोग करते हैं, क्योंकि आप अक्सर उपवर्गों में गुणों को फिर से परिभाषित नहीं करते हैं; एक staticलेट-बाउंड कंस्ट्रक्टर को आमंत्रित करने के लिए कीवर्ड का उपयोग करने का एक उदाहरण इस संबंधित प्रश्न में पाया जा सकता है: नया स्व बनाम नया स्थिर

हालाँकि, यह staticगुण के साथ भी उपयोग नहीं करता है ।


आप बच्चे की कक्षा में बहुत आसानी से रिडक्लेयर कर सकते हैं, अभिभावक वर्ग एक डिफ़ॉल्ट मान हो सकता है जो चाइल्ड क्लास तब तक उपयोग करता है जब तक कि वे पुनः घोषित न करें। यदि आप अभिभावक वर्ग में हैं, तो मुझे लगता है कि स्वयं का उपयोग करना सुरक्षित है ::, और यदि बाल वर्ग में, आप किसी एक का उपयोग करने के तर्क के साथ आ सकते हैं, लेकिन स्वयं :: यदि आप अपेक्षा नहीं करते हैं तो भी यह काम करेगा। फिर से घोषित
एंड्रयू

3
phpfiddle.org पर जाएं और इसे चलाएं<?php class Foo { public static $bar = 1234; public static function a( ) { echo 'static'.static::$bar; echo 'self'.self::$bar; } } class Bar extends Foo { public static $bar = 4321; } (new Bar())->a(); ?>
येवगेनी

2
पहले दो पैराग्राफ शब्दों को भ्रमित करने वाला है, एक अस्पष्ट सर्वनाम है, "यह", और यह भी निरर्थक है, क्योंकि बाद के पैराग्राफ समान जानकारी को अधिक स्पष्ट रूप से बताते हैं। मैं पहले दो पैराग्राफ को बाद के पैराग्राफ से बदलने का सुझाव देता हूं जो "ऊपर के परिदृश्य में" शीर्ष से शुरू होता है। इस तरह से नीचे की रेखा, कट-टू-चेस जवाब सबसे ऊपर है। यह स्पष्ट और पालन करने में आसान है।
अहानिबेकाड

इस बारे में सोचने का एक और तरीका: self::$abcजब अंदर इस्तेमाल किया जाता है, तो class Fooयह कहने जैसा ही है Foo::$abc। यह $abcएक उपवर्ग में किसी भी पुनः घोषणा से प्रभावित नहीं होगा । AFAIK, उपयोग करने का एकमात्र कारण selfशॉर्टहैंड के रूप में है, वर्ग नाम का उपयोग करने से बचने के लिए Foo, जो अधिक लंबा हो सकता है। [इसका मतलब यह भी है कि आप उन सभी स्थानों को बदले बिना classname बदल सकते हैं - लेकिन यह IMHO का एक कारण नहीं है।] (PHP के नामों की पसंद दुर्भाग्यपूर्ण है, और पीछे की ओर लगता है; "स्थिर" वह है जो बदल सकता है - जो प्राकृतिक भाषा के शब्द "स्टैटिक" के बोलचाल के अर्थ के विपरीत है।)
टूलमेकर

4

जैसा कि मुख्य अंतरों में से एक है कि staticदेर से स्थैतिक बाइंडिंग के लिए अनुमति देता है। सबसे उपयोगी परिदृश्यों में से एक जो मुझे मिला, वह सिंगलटन क्लासेस के लिए बेस क्लास बनाने के लिए था:

class A { // Base Class
    protected static $name = '';
    protected static function getName() {
        return static::$name;
    }
}
class B extends A {
    protected static $name = 'MyCustomNameB';
}
class C extends A {
    protected static $name = 'MyCustomNameC';
}

echo B::getName(); // MyCustomNameB
echo C::getName(); // MyCustomNameC

return static::$nameबेस क्लास का उपयोग करने पर वह वापस आ जाएगा, जो विस्तारित होने पर वैधानिक रूप से संलग्न था। यदि आप उपयोग करना चाहते थे return self::$nameतो B::getName()एक खाली स्ट्रिंग लौटा देंगे जैसा कि बेस क्लास में घोषित किया गया है।


0

selfकॉल के साथ :

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return self::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "123"
echo (new Bar)->getVar();

आप ऊपर देख सकते हैं, भले ही हमने $varअपनी Barकक्षा के साथ ओवरराइड किया है , यह अभी भी वापस आ गया है 123, क्योंकि हमने स्पष्ट रूप से PHP के लिए selfचर के लिए कहा है , जो बदले में पूछता हैFoo चर के ।

अब अगर हम कॉल को स्वैप करते हैं static, तो हम बदले में Barओवरराइड वैल्यू प्राप्त करेंगे :

staticकॉल के साथ :

class Foo
{
    protected static $var = 123;
    
    public function getVar()
    {
        return static::$var;
    }
}

class Bar extends Foo
{
    protected static $var = 234;
}

// Displays: "234"
echo (new Bar)->getVar();
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.