php $ $ से अधिक का उपयोग कब करें?




बच्चों को गणित कैसे सिखाए (17)

वास्तव में यह समझने के लिए कि जब हम self बनाम इसके बारे में बात करते हैं, तो हम वास्तव में क्या सोच रहे हैं, हमें वास्तव में एक वैचारिक और व्यावहारिक स्तर पर क्या हो रहा है, इसमें खोदने की आवश्यकता है। मुझे वास्तव में कोई भी जवाब उचित तरीके से महसूस नहीं करता है, इसलिए मेरा प्रयास यहां है।

आइए कक्षा और वस्तु क्या है, इस बारे में बात करके शुरू करें।

अवधारणाओं और वस्तुओं, अवधारणात्मक रूप से

तो, कक्षा क्या है ? बहुत से लोग इसे किसी ऑब्जेक्ट के लिए ब्लूप्रिंट या टेम्पलेट के रूप में परिभाषित करते हैं। वास्तव में, आप यहां PHP में कक्षाओं के बारे में अधिक पढ़ सकते हैं। और कुछ हद तक यह वास्तव में क्या है। आइए कक्षा को देखें:

class Person {
    public $name = 'my name';
    public function sayHello() {
        echo "Hello";
    }
}

जैसा कि आप बता सकते हैं, उस वर्ग पर एक संपत्ति है जिसे $name और एक विधि (फ़ंक्शन) कहा जाता है जिसे sayHello() कहा जाता है।

यह ध्यान रखना बहुत महत्वपूर्ण है कि कक्षा एक स्थिर संरचना है। जिसका अर्थ है कि एक बार परिभाषित वर्ग Person हमेशा हर जगह वही होता है जहां आप इसे देखते हैं।

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

$bob = new Person;
$adam = new Person;
$bob->name = 'Bob';
echo $adam->name; // "my name"

हम new ऑपरेटर का उपयोग कर कक्षा के नए उदाहरण बनाते हैं।

इसलिए, हम कहते हैं कि एक वर्ग एक वैश्विक संरचना है, और एक वस्तु एक स्थानीय संरचना है। उस अजीब -> वाक्यविन्यास के बारे में चिंता न करें, हम उसमें थोड़ी देर में जा रहे हैं।

एक और बात जिसके बारे में हमें बात करनी चाहिए, यह है कि हम यह जांच सकते हैं कि कोई instanceof किसी विशेष वर्ग का instanceof है: $bob instanceof Person जो $bob instanceof Person बूलियन देता है यदि $bob उदाहरण Person वर्ग या Person बच्चे का उपयोग करके किया गया था।

राज्य परिभाषित करना

तो चलिए थोड़ा सा खोदते हैं जिसमें एक कक्षा वास्तव में होती है। 5 प्रकार की "चीजें" हैं जिनमें कक्षा में शामिल हैं:

  1. गुण - इन्हें चर के रूप में सोचें कि प्रत्येक उदाहरण में शामिल होगा।

    class Foo {
        public $bar = 1;
    }
    
  2. स्टेटिक प्रॉपर्टीज - इन्हें कक्षा के स्तर पर साझा किए जाने वाले चर के रूप में सोचें। मतलब है कि वे प्रत्येक उदाहरण द्वारा कभी कॉपी नहीं किया जाता है।

    class Foo {
        public static $bar = 1;
    }
    
  3. तरीके - ये वे कार्य हैं जिनमें प्रत्येक उदाहरण शामिल होगा (और उदाहरणों पर कार्य करें)।

    class Foo {
        public function bar() {}
    }
    
  4. स्टेटिक तरीके - ये वे कार्य हैं जो पूरे वर्ग में साझा किए जाते हैं। वे उदाहरणों पर काम नहीं करते हैं, बल्कि इसके बजाय स्थिर गुणों पर भी काम करते हैं।

    class Foo {
        public static function bar() {}
    }
    
  5. Constants - वर्ग संकल्प स्थिरांक। यहां कोई गहराई से नहीं जा रहा है, लेकिन पूर्णता के लिए जोड़ना:

    class Foo {
        const BAR = 1;
    }
    

इसलिए मूल रूप से, हम क्लास के बारे में "संकेत" का उपयोग करके कक्षा और ऑब्जेक्ट कंटेनर पर जानकारी संग्रहीत कर रहे हैं जो यह पहचानता है कि जानकारी साझा की गई है (और इसलिए स्थैतिक) या नहीं (और इसलिए गतिशील)।

राज्य और तरीके

एक विधि के अंदर, एक ऑब्जेक्ट का उदाहरण $this चर द्वारा दर्शाया गया है। उस वस्तु की वर्तमान स्थिति वहां है, और किसी भी संपत्ति को बदलना (बदलना) परिणामस्वरूप उस उदाहरण में परिवर्तन होगा (लेकिन दूसरों को नहीं)।

यदि किसी विधि को स्थैतिक रूप से कहा जाता है, तो $this चर परिभाषित नहीं किया गया है । ऐसा इसलिए है क्योंकि एक स्थिर कॉल से जुड़े कोई उदाहरण नहीं है।

यहां दिलचस्प बात यह है कि स्थिर कॉल कैसे किए जाते हैं। तो आइए बात करें कि हम कैसे राज्य तक पहुंचते हैं:

राज्य तक पहुंच

तो अब जब हमने उस राज्य को संग्रहित किया है, तो हमें इसे एक्सेस करने की आवश्यकता है। यह थोड़ा मुश्किल हो सकता है (या थोड़ी से अधिक रास्ता ), तो चलिए इसे दो दृष्टिकोणों में विभाजित करते हैं: एक उदाहरण / कक्षा के बाहर से (सामान्य फ़ंक्शन कॉल से या वैश्विक दायरे से), और एक उदाहरण के अंदर / वर्ग (वस्तु पर एक विधि के भीतर से)।

एक उदाहरण / कक्षा के बाहर से

एक उदाहरण / कक्षा के बाहर से, हमारे नियम काफी सरल और अनुमानित हैं। हमारे पास दो ऑपरेटर हैं, और प्रत्येक हमें तत्काल बताता है अगर हम किसी उदाहरण या क्लास स्टेटिक से निपट रहे हैं:

  • -> - ऑब्जेक्ट-ऑपरेटर - जब हम किसी उदाहरण का उपयोग कर रहे होते हैं तो इसका हमेशा उपयोग होता है।

    $bob = new Person;
    echo $bob->name;
    

    यह ध्यान रखना महत्वपूर्ण है कि Person->foo कॉल Person->foo समझ में नहीं आता है (क्योंकि Person एक वर्ग है, उदाहरण नहीं है)। इसलिए, यह एक पार्स त्रुटि है।

  • :: - स्कोप-रेज़ोल्यूशन-ऑपरेटर - यह हमेशा क्लास स्थैतिक संपत्ति या विधि तक पहुंचने के लिए उपयोग किया जाता है।

    echo Foo::bar()
    

    इसके अतिरिक्त, हम किसी ऑब्जेक्ट पर एक स्थिर विधि को उसी तरह कॉल कर सकते हैं:

    echo $foo::bar()
    

    यह ध्यान रखना बेहद महत्वपूर्ण है कि जब हम इसे बाहर से करते हैं, तो ऑब्जेक्ट का उदाहरण bar() विधि से छिपा हुआ है। मतलब यह है कि यह चलने जैसा सटीक है:

    $class = get_class($foo);
    $class::bar();
    

इसलिए, $this स्थिर कॉल में परिभाषित नहीं है।

एक इंस्टेंस / कक्षा के अंदर से

चीजें यहाँ थोड़ा बदलती हैं। एक ही ऑपरेटर का उपयोग किया जाता है, लेकिन उनका अर्थ काफी धुंधला हो जाता है।

ऑब्जेक्ट-ऑपरेटर -> अभी भी ऑब्जेक्ट के इंस्टेंस स्टेटस पर कॉल करने के लिए उपयोग किया जाता है।

class Foo {
    public $a = 1;
    public function bar() {
        return $this->a;
    }
}

ऑब्जेक्ट-ऑपरेटर का उपयोग करके $foo ( Foo का एक उदाहरण bar() पर bar() विधि को कॉल करना: $foo->bar() परिणामस्वरूप $a का संस्करण संस्करण होगा।

तो हम इस तरह की उम्मीद करते हैं।

हालांकि :: ऑपरेटर का अर्थ बदलता है। यह वर्तमान फ़ंक्शन को कॉल के संदर्भ पर निर्भर करता है:

  • एक स्थिर संदर्भ के भीतर

    एक स्थिर संदर्भ के भीतर, :: का उपयोग कर किए गए किसी भी कॉल स्थिर भी होंगे। आइए एक उदाहरण देखें:

    class Foo {
        public function bar() {
            return Foo::baz();
        }
        public function baz() {
            return isset($this);
        }
    }
    

    कॉलिंग Foo::bar() baz() विधि को स्थिर रूप से कॉल करेगा, और इसलिए $this पॉप्युलेट नहीं होगा। यह ध्यान देने योग्य है कि PHP (5.3+) के हाल के संस्करणों में यह एक E_STRICT त्रुटि ट्रिगर करेगा, क्योंकि हम स्थैतिक रूप से गैर स्थैतिक तरीकों को कॉल कर रहे हैं।

  • एक उदाहरण संदर्भ के भीतर

    दूसरी तरफ एक संदर्भ संदर्भ के भीतर, कॉल का उपयोग करने वाले कॉल (कॉल के प्राप्तकर्ता (जिस विधि को हम बुला रहे हैं) पर निर्भर करते हैं। यदि विधि को static रूप में परिभाषित किया गया है, तो यह एक स्थिर कॉल का उपयोग करेगा। यदि ऐसा नहीं है, तो यह इंस्टेंस जानकारी अग्रेषित करेगा।

    तो, उपर्युक्त कोड को देखते हुए, $foo->bar() को कॉल करना true हो जाएगा, क्योंकि "स्थैतिक" कॉल एक उदाहरण संदर्भ के अंदर होती है।

सही बात? ऐसा नहीं सोचा था। यह भ्रमित करने वाला है।

लघु कट कीवर्ड

चूंकि वर्ग नामों का उपयोग करके सबकुछ एक साथ बांधना गंदा है, इसलिए PHP स्कोप को हल करने में आसान बनाने के लिए 3 बुनियादी "शॉर्टकट" कीवर्ड प्रदान करता है।

  • self - यह वर्तमान वर्ग नाम को संदर्भित करता है। तो self::baz() Foo::baz() के रूप में Foo वर्ग (उस पर कोई भी विधि) के समान है।

  • parent - यह वर्तमान वर्ग के माता-पिता को संदर्भित करता है।

  • static - यह बुलाया वर्ग को संदर्भित करता है। विरासत के लिए धन्यवाद, बाल वर्ग विधियों और स्थिर गुणों को ओवरराइड कर सकते हैं। इसलिए उन्हें क्लास नाम के बजाय static का उपयोग करके कॉल करना हमें वर्तमान स्तर की बजाय कॉल कहां से आया, यह हल करने की अनुमति देता है।

उदाहरण

इसे समझने का सबसे आसान तरीका कुछ उदाहरणों को देखना शुरू करना है। आइए कक्षा चुनें:

class Person {
    public static $number = 0;
    public $id = 0;
    public function __construct() {
        self::$number++;
        $this->id = self::$number;
    }
    public $name = "";
    public function getName() {
        return $this->name;
    }
    public function getId() {
        return $this->id;
    }
}

class Child extends Person {
    public $age = 0;
    public function __construct($age) {
        $this->age = $age;
        parent::__construct();
    }
    public function getName() {
        return 'child: ' . parent::getName();
    }
}

अब, हम यहां विरासत को भी देख रहे हैं। एक पल के लिए अनदेखा करें कि यह एक बुरा ऑब्जेक्ट मॉडल है, लेकिन देखते हैं कि जब हम इसके साथ खेलते हैं तो क्या होता है:

$bob = new Person;
$bob->name = "Bob";
$adam = new Person;
$adam->name = "Adam";
$billy = new Child;
$billy->name = "Billy";
var_dump($bob->getId()); // 1
var_dump($adam->getId()); // 2
var_dump($billy->getId()); // 3

तो आईडी काउंटर दोनों उदाहरणों और बच्चों में साझा किया जाता है (क्योंकि हम इसे एक्सेस करने के लिए self का उपयोग कर रहे हैं। अगर हम static इस्तेमाल static , तो हम इसे बाल वर्ग में ओवरराइड कर सकते हैं)।

var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy

ध्यान दें कि हम हर बार Person::getName() इंस्टेंस विधि निष्पादित कर रहे हैं। लेकिन हम parent::getName() को किसी एक मामले (बच्चे के मामले) में करने के लिए उपयोग कर रहे हैं। यह इस दृष्टिकोण को शक्तिशाली बनाता है।

सावधानी का शब्द # 1

ध्यान दें कि कॉलिंग संदर्भ यह निर्धारित करता है कि कोई उदाहरण उपयोग किया जाता है या नहीं। इसलिए:

class Foo {
    public function isFoo() {
        return $this instanceof Foo;
    }
}

हमेशा सच नहीं है।

class Bar {
    public function doSomething() {
        return Foo::isFoo();
    }
}
$b = new Bar;
var_dump($b->doSomething()); // bool(false)

अब यह वास्तव में अजीब है। हम एक अलग वर्ग को बुला रहे हैं, लेकिन यह $this Foo::isFoo() विधि में पारित होने वाला $bar का उदाहरण है।

यह सभी प्रकार की बग और वैचारिक डब्ल्यूटीएफ-ery का कारण बन सकता है। तो मैं उन तीन वर्चुअल "शॉर्ट-कट" कीवर्ड ( static , self और parent ) को छोड़कर किसी भी चीज़ पर उदाहरण के तरीकों से :: ऑपरेटर से बचने का सुझाव देता हूं।

सावधानी का शब्द # 2

ध्यान दें कि स्थिर तरीकों और गुण सभी के द्वारा साझा किए जाते हैं। यह उन्हें मूल रूप से वैश्विक चर बनाता है। ग्लोबल्स के साथ आने वाली सभी समस्याओं के साथ। तो मैं स्थिर तरीकों / गुणों में जानकारी संग्रहीत करने में वास्तव में संकोच नहीं करूँगा जबतक कि आप वास्तव में वैश्विक होने के साथ सहज महसूस न करें।

सावधानी का शब्द # 3

आम तौर पर आप self बजाय static उपयोग करके लेट-स्टेटिक-बाध्यकारी के रूप में जाना जाता है। लेकिन ध्यान दें कि वे एक ही बात नहीं हैं, इसलिए कह रहे हैं "हमेशा self बजाय static उपयोग करना वास्तव में कम दिखता है। इसके बजाय, उस कॉल के बारे में सोचें और सोचें जिसे आप बनाना चाहते हैं और सोचें कि क्या आप चाहते हैं कि बाल कक्षाएं इसे ओवरराइड कर सकें स्थिर हल कॉल।

टीएल / डॉ

बहुत बुरा, वापस जाओ और इसे पढ़ें। यह बहुत लंबा हो सकता है, लेकिन यह इतना लंबा है क्योंकि यह एक जटिल विषय है

टीएल / डीआर # 2

अच्छी बात है। संक्षेप में, self वर्ग के वर्तमान वर्ग नाम को संदर्भित करने के लिए self का उपयोग किया जाता है, जहां $this वर्तमान ऑब्जेक्ट उदाहरण को संदर्भित करता है। ध्यान दें कि self एक कॉपी / पेस्ट शॉर्ट-कट है। आप इसे अपने वर्ग के नाम से सुरक्षित रूप से प्रतिस्थापित कर सकते हैं, और यह ठीक काम करेगा। लेकिन $this एक गतिशील चर है जिसे समय से पहले निर्धारित नहीं किया जा सकता है (और यहां तक ​​कि आपकी कक्षा भी नहीं हो सकती है)।

टीएल / डीआर # 3

यदि ऑब्जेक्ट-ऑपरेटर का उपयोग किया जाता है ( -> ), तो आप हमेशा जानते हैं कि आप एक उदाहरण से निपट रहे हैं। यदि स्कोप-रिज़ॉल्यूशन-ऑपरेटर का उपयोग किया जाता है ( :: :), आपको संदर्भ के बारे में अधिक जानकारी चाहिए (क्या हम पहले से ही ऑब्जेक्ट-संदर्भ में हैं? क्या हम किसी ऑब्जेक्ट के बाहर हैं? आदि)।

PHP 5 में, self और $this का उपयोग करने के बीच क्या अंतर है?

प्रत्येक उपयुक्त कब है?


Use self if you want to call a method of a class without creating an object/instance of that class, thus saving RAM (sometimes use self for that purpose). In other words, it is actually calling a method statically. Use this for object perspective.


Php.net के अनुसार इस संदर्भ में तीन विशेष कीवर्ड होते हैं: self, parentऔर static। वे कक्षा परिभाषा के अंदर से गुणों या विधियों तक पहुंचने के लिए उपयोग किया जाता है।

$this दूसरी ओर, किसी भी वर्ग के उदाहरण और विधियों को कॉल करने के लिए उपयोग किया जाता है जब तक वह कक्षा सुलभ हो।


$this-> का उपयोग किसी वर्ग के चर (सदस्य चर) या विधियों के विशिष्ट उदाहरण को संदर्भित करने के लिए किया जाता है।

Example: 
$derek = new Person();

$ डेरेक अब व्यक्ति का एक विशिष्ट उदाहरण है। प्रत्येक व्यक्ति का पहला_नाम और अंतिम_नाम होता है, लेकिन $ डेरेक का एक विशिष्ट first_name और last_name (डेरेक मार्टिन) होता है। $ डेरेक उदाहरण के अंदर, हम उन्हें $-- first_name और $ this-> last_name के रूप में संदर्भित कर सकते हैं

क्लासनाम :: का उपयोग उस प्रकार के वर्ग, और इसके स्थैतिक चर, स्थिर तरीकों के संदर्भ में किया जाता है। यदि यह मदद करता है, तो आप मानसिक रूप से "स्थिर" शब्द को "साझा" से प्रतिस्थापित कर सकते हैं। क्योंकि वे साझा किए जाते हैं, वे इसका उल्लेख नहीं कर सकते हैं, जो एक विशिष्ट उदाहरण (साझा नहीं किया गया) को संदर्भित करता है। स्टेटिक वैरिएबल (यानी स्थिर $ db_connection) किसी ऑब्जेक्ट के सभी उदाहरणों के बीच साझा किया जा सकता है। उदाहरण के लिए, सभी डेटाबेस ऑब्जेक्ट्स एक एकल कनेक्शन (स्थिर $ कनेक्शन) साझा करते हैं।

स्टेटिक वैरिएबल उदाहरण: दिखाएं कि हमारे पास एक सदस्य वर्ग के साथ डेटाबेस क्लास है: स्थिर $ num_connections; अब, इसे कन्स्ट्रक्टर में रखें:

function __construct()
{
    if(!isset $num_connections || $num_connections==null)
    {
        $num_connections=0;
    }
    else
    {
        $num_connections++;
    }
}

जैसे वस्तुओं में रचनाकार होते हैं, उनके पास विनाशक भी होते हैं, जिन्हें ऑब्जेक्ट मर जाता है या अनसेट होने पर निष्पादित किया जाता है:

function __destruct()
{
    $num_connections--;
}

हर बार जब हम एक नया उदाहरण बनाते हैं, तो यह हमारे कनेक्शन काउंटर को एक से बढ़ा देगा। हर बार जब हम किसी उदाहरण का उपयोग करते हैं या रोकते हैं, तो यह कनेक्शन काउंटर को एक से कम कर देगा। इस तरह, हम डेटाबेस ऑब्जेक्ट के उदाहरणों की संख्या की निगरानी कर सकते हैं जिनके साथ हम उपयोग में हैं:

echo DB::num_connections;

चूंकि $ num_connections स्थिर (साझा) है, यह सक्रिय डेटाबेस ऑब्जेक्ट्स की कुल संख्या को प्रतिबिंबित करेगा। आपने इस तकनीक को डेटाबेस क्लास के सभी उदाहरणों के बीच डेटाबेस कनेक्शन साझा करने के लिए उपयोग किया होगा। ऐसा इसलिए किया जाता है क्योंकि डेटाबेस कनेक्शन बनाने में काफी समय लगता है, इसलिए इसे केवल एक बनाना और इसे साझा करना सर्वोत्तम है (इसे सिंगलटन पैटर्न कहा जाता है)।

स्टेटिक तरीके (यानी सार्वजनिक स्थैतिक दृश्य :: format_phone_number ($ अंक)) का उपयोग उन वस्तुओं में से किसी एक को तत्काल करने के बिना किया जा सकता है (यानी वे आंतरिक रूप से इसका उल्लेख नहीं करते हैं)।

स्टेटिक विधि उदाहरण:

public static function prettyName($first_name, $last_name)
{
    echo ucfirst($first_name).' '.ucfirst($last_name);
}

echo Person::prettyName($derek->first_name, $derek->last_name);

जैसा कि आप देख सकते हैं, सार्वजनिक स्थैतिक फ़ंक्शन prettyName ऑब्जेक्ट के बारे में कुछ भी नहीं जानता है। यह सिर्फ आपके द्वारा पारित पैरामीटर के साथ काम कर रहा है, एक सामान्य फ़ंक्शन की तरह जो किसी ऑब्जेक्ट का हिस्सा नहीं है। फिर परेशान क्यों करें, अगर हम इसे वस्तु के हिस्से के रूप में नहीं ले सकते हैं?

  1. सबसे पहले, वस्तुओं को कार्यों को जोड़ने से आप चीजों को संगठित रखने में मदद कर सकते हैं, ताकि आपको पता चले कि उन्हें कहां मिलना है।
  2. दूसरा, यह नामकरण संघर्ष रोकता है। एक बड़ी परियोजना में, आपके पास दो डेवलपर्स getName () फ़ंक्शंस बनाने की संभावना है। यदि कोई क्लासनाम 1 :: getName () बनाता है, और दूसरा क्लासनाम 2 :: getName () बनाता है, तो यह कोई समस्या नहीं है। कोई विवाद नहीं। हाँ स्थैतिक तरीकों!

SELF :: यदि आप उस ऑब्जेक्ट के बाहर कोडिंग कर रहे हैं जिसमें स्थिर विधि है जिसे आप संदर्भित करना चाहते हैं, तो आपको इसे ऑब्जेक्ट के नाम का उपयोग करके कॉल करना होगा :: format_phone_number ($ phone_number); यदि आप उस ऑब्जेक्ट के अंदर कोडिंग कर रहे हैं जिसमें स्थिर विधि है जिसे आप संदर्भित करना चाहते हैं, तो आप या तो ऑब्जेक्ट का नाम देखें :: format_phone_number ($ pn), या आप स्वयं :: format_phone_number ($ pn) शॉर्टकट का उपयोग कर सकते हैं

स्थिर चर के लिए भी यही है: उदाहरण: देखें :: templates_path बनाम स्वयं :: templates_path

डीबी कक्षा के अंदर, अगर हम किसी अन्य वस्तु की स्थिर विधि का जिक्र कर रहे थे, तो हम वस्तु के नाम का उपयोग करेंगे: उदाहरण: सत्र :: getUsersOnline ();

लेकिन अगर डीबी वर्ग अपने स्थैतिक चर को संदर्भित करना चाहता था, तो यह केवल स्वयं कहता है: उदाहरण: स्वयं :: कनेक्शन;

उम्मीद है कि चीजों को साफ़ करने में मदद करता है :)


जैसा कि यहां कोई भी प्रदर्शन के बारे में बात नहीं करता है, यहां मैंने एक छोटा बेंचमार्क किया है (5.6):

 Name     | Time    | Percent  
----------|---------|---------  
 $this->  | 0.99163 | 106.23%  
 self::   | 0.96912 | 103.82%  
 static:: | 0.93348 | 100%

वे 2 000 000 रन के परिणाम हैं, और यहां कोड का उपयोग किया गया है:

<?php

require '../vendor/autoload.php';

// My small class to do benchmarks
// All it does is looping over every test x times and record the
//   time it takes using `microtime(true)`
// Then, the percentage is calculated, with 100% being the quickest
// Times are being rouned for outputting only, not to calculate the percentages
$b = new Tleb\Benchmark\Benchmark(2000000);

class Foo
{
    public function calling_this()
    {
        $this->called();
    }

    public function calling_self()
    {
        self::called();
    }

    public function calling_static()
    {
        static::called();
    }

    public static function called()
    {
    }
}

$b->add('$this->',  function () { $foo = new Foo; $foo->calling_this(); });
$b->add('self::',   function () { $foo = new Foo; $foo->calling_self(); });
$b->add('static::', function () { $foo = new Foo; $foo->calling_static(); });

$b->run();

http://www.php.net/manual/en/language.oop5.static.php अनुसार कोई $self । कक्षा (वस्तु), और स्वयं के वर्तमान उदाहरण का जिक्र करने के लिए केवल $this , जिसका उपयोग कक्षा के स्थिर सदस्यों को संदर्भित करने के लिए किया जा सकता है। ऑब्जेक्ट इंस्टेंस और क्लास के बीच का अंतर यहां खेलता है।


PHP में, आप स्थिर गुणों और विधियों तक पहुंचने के लिए स्वयं कीवर्ड का उपयोग करते हैं।

समस्या यह है कि आप $this->method() self::method() $this->method() को self::method() कहीं भी प्रतिस्थापित कर सकते हैं, भले ही method() को स्थिर घोषित किया गया हो या नहीं। तो आप किस का उपयोग करना चाहिए?

इस कोड पर विचार करें:

class ParentClass {
    function test() {
        self::who();    // will output 'parent'
        $this->who();   // will output 'child'
    }

    function who() {
        echo 'parent';
    }
}

class ChildClass extends ParentClass {
    function who() {
        echo 'child';
    }
}

$obj = new ChildClass();
$obj->test();

इस उदाहरण में, self::who() हमेशा 'पैरेंट' आउटपुट करेगा, जबकि $this->who() इस बात पर निर्भर करेगा कि ऑब्जेक्ट के किस वर्ग पर है।

अब हम देख सकते हैं कि स्वयं उस वर्ग को संदर्भित करता है जिसमें इसे कहा जाता है, जबकि $this वर्तमान वस्तु के वर्ग को संदर्भित करता है।

इसलिए, आपको केवल तभी उपयोग करना चाहिए जब $this उपलब्ध न हो, या जब आप वर्तमान वर्ग को ओवरराइट करने के लिए वंशज वर्गों को अनुमति नहीं देना चाहते हैं।


self:: उपयोग न करें self:: static::

आत्म :: का एक और पहलू है जो उल्लेखनीय है। कष्टप्रद self:: निष्पादन के बिंदु पर परिभाषा के बिंदु पर दायरे को संदर्भित करता है । दो सरल तरीकों से इस सरल वर्ग पर विचार करें:

class Person
{

    public static function status()
    {
        self::getStatus();
    }

    protected static function getStatus()
    {
        echo "Person is alive";
    }

}

अगर हम Person::status() कॉल करते हैं तो हम देखेंगे "व्यक्ति जीवित है"। अब विचार करें कि क्या होता है जब हम उस वर्ग को प्राप्त करते हैं जो इस से प्राप्त होता है:

class Deceased extends Person
{

    protected static function getStatus()
    {
        echo "Person is deceased";
    }

}

कॉलिंग Deceased::status() हम "व्यक्ति मर चुके हैं" को देखने की उम्मीद करेंगे, हालांकि हम जो देखते हैं वह "व्यक्ति जीवित है" क्योंकि स्कोप में मूल विधि परिभाषा होती है जब self::getStatus() को परिभाषित किया गया था।

PHP 5.3 में एक समाधान है। static:: रिज़ॉल्यूशन ऑपरेटर "देर से स्थिर बाध्यकारी" लागू करता है जो कहने का एक शानदार तरीका है कि इसे कक्षा के दायरे से बंधे हुए हैं। status() में status() को static::getStatus() में बदलें और परिणाम आप अपेक्षा करेंगे। PHP के पुराने संस्करणों में आपको ऐसा करने के लिए एक क्लज खोजना होगा।

PHP दस्तावेज़ीकरण देखें

इसलिए सवाल का जवाब देने के लिए नहीं ...

$this-> वर्तमान वस्तु (कक्षा का एक उदाहरण) को संदर्भित करता है, जबकि static:: एक वर्ग को संदर्भित करता है


  • वर्तमान ऑब्जेक्ट को संदर्भित करने के लिए ऑब्जेक्ट पॉइंटर $ यह है।
  • वर्ग मूल्य "स्थैतिक" वर्तमान वस्तु को संदर्भित करता है।
  • वर्ग मूल्य "स्वयं" उस सटीक वर्ग को संदर्भित करता है जिसे परिभाषित किया गया था।
  • वर्ग मान "अभिभावक" उस सटीक वर्ग के माता-पिता को संदर्भित करता है जिसे परिभाषित किया गया था।

निम्न उदाहरण देखें जो ओवरलोडिंग दिखाता है।

<?php

class A {

    public static function newStaticClass()
    {
        return new static;
    }

    public static function newSelfClass()
    {
        return new self;
    }

    public function newThisClass()
    {
        return new $this;
    }
}

class B extends A
{
    public function newParentClass()
    {
        return new parent;
    }
}


$b = new B;

var_dump($b::newStaticClass()); // B
var_dump($b::newSelfClass()); // A because self belongs to "A"
var_dump($b->newThisClass()); // B
var_dump($b->newParentClass()); // A


class C extends B
{
    public static function newSelfClass()
    {
        return new self;
    }
}


$c = new C;

var_dump($c::newStaticClass()); // C
var_dump($c::newSelfClass()); // C because self now points to "C" class
var_dump($c->newThisClass()); // C
var_dump($b->newParentClass()); // A because parent was defined *way back* in class "B"

अधिकांश समय आप वर्तमान कक्षा को संदर्भित करना चाहते हैं, यही कारण है कि आप static या $this उपयोग $this । हालांकि, ऐसे समय होते हैं जब आपको self आवश्यकता होती है क्योंकि आप मूल वर्ग चाहते हैं चाहे उसे विस्तारित किया जाए। (बहुत, बहुत ही कम)


$this refers to the current class object, self refers to the current class (Not object). The class is the blueprint of the object. So you define a class, but you construct objects.

So in other words, use self for static and this for none-static members or methods .

also in child/parent scenario self / parent is mostly used to identified child and parent class members and methods.


जब :: ऑपरेटर के साथ self का उपयोग किया जाता है तो यह वर्तमान वर्ग को संदर्भित करता है, जो स्थिर और गैर स्थैतिक संदर्भ दोनों में किया जा सकता है। $this वस्तु को ही संदर्भित करता है। इसके अलावा, स्थिर विधियों को कॉल करने के लिए $this का उपयोग करना पूरी तरह से कानूनी है (लेकिन फ़ील्ड को संदर्भित नहीं करना)।


संक्षिप्त जवाब

वर्तमान ऑब्जेक्ट को संदर्भित करने के लिए $this उपयोग करें। वर्तमान वर्ग को संदर्भित करने के लिए self का प्रयोग करें। दूसरे शब्दों में, गैर-स्थैतिक सदस्यों के लिए $this->member उपयोग करें, स्थिर सदस्यों के लिए self::$member उपयोग करें।

पूरा उत्तर

यहां $this के सही उपयोग और गैर स्थैतिक और स्थैतिक सदस्य चर के लिए self का एक उदाहरण दिया गया है:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?>

यहां $this के गलत उपयोग और गैर स्थैतिक और स्थैतिक सदस्य चर के लिए self का एक उदाहरण दिया गया है:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo self::$non_static_member . ' '
           . $this->static_member;
    }
}

new X();
?>

यहां सदस्य कार्यों के लिए $this 1.2 के साथ बहुरूपता का एक उदाहरण दिया गया है:

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        $this->foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

सदस्य कार्यों के लिए self का उपयोग करके पॉलिमॉर्फिक व्यवहार को दबाने का एक उदाहरण यहां दिया गया है:

<?php
class X {
    function foo() {
        echo 'X::foo()';
    }

    function bar() {
        self::foo();
    }
}

class Y extends X {
    function foo() {
        echo 'Y::foo()';
    }
}

$x = new Y();
$x->bar();
?>

विचार यह है कि $this->foo() जो भी> foo() सदस्य फ़ंक्शन को कॉल करता है> वर्तमान ऑब्जेक्ट का सटीक प्रकार है। यदि ऑब्जेक्ट type X , तो इस प्रकार> X::foo() कॉल करता है। यदि ऑब्जेक्ट type Y , तो यह Y::foo() कॉल करता है। लेकिन साथ> self :: foo (), X::foo() हमेशा कहा जाता है।

http://www.phpbuilder.com/board/showthread.php?t=10354489 :

http://board.phpbuilder.com/member.php?145249-laserlight द्वारा


self वर्तमान वर्ग को संदर्भित करता है (जिसमें इसे कहा जाता है)

$this वर्तमान वस्तु को संदर्भित करता है। आप स्वयं के बजाय स्थिर का उपयोग कर सकते हैं। उदाहरण देखें:

    class ParentClass {
            function test() {
                    self::which();  // output 'parent'
                    $this->which(); // output 'child'
            }

            function which() {
                    echo 'parent';
            }
    }

    class ChildClass extends ParentClass {
            function which() {
                    echo 'child';
            }
    }

    $obj = new ChildClass();
    $obj->test();

आउटपुट: माता-पिता बच्चे


यहां $ $ के सही उपयोग और गैर स्थैतिक और स्थैतिक सदस्य चर के लिए स्वयं का एक उदाहरण दिया गया है:

<?php
class X {
    private $non_static_member = 1;
    private static $static_member = 2;

    function __construct() {
        echo $this->non_static_member . ' '
           . self::$static_member;
    }
}

new X();
?> 

कीवर्ड स्वयं केवल 'वर्तमान वर्ग' को संदर्भित नहीं करता है, कम से कम इस तरह से नहीं है जो आपको स्थिर सदस्यों को प्रतिबंधित करता है। एक गैर स्थैतिक सदस्य के संदर्भ में, self वर्तमान वस्तु के लिए vtable ( vtable पर विकी देखें ) को छोड़ने का एक तरीका भी प्रदान करता है। जैसे ही आप किसी फ़ंक्शन के माता-पिता संस्करण को कॉल करने के लिए parent::methodName() का उपयोग कर सकते हैं, ताकि आप एक विधि के वर्तमान वर्ग कार्यान्वयन को कॉल करने के लिए self::methodName() को कॉल कर सकें।

class Person {
    private $name;

    public function __construct($name) {
        $this->name = $name;
    }

    public function getName() {
        return $this->name;
    }

    public function getTitle() {
        return $this->getName()." the person";
    }

    public function sayHello() {
        echo "Hello, I'm ".$this->getTitle()."<br/>";
    }

    public function sayGoodbye() {
        echo "Goodbye from ".self::getTitle()."<br/>";
    }
}

class Geek extends Person {
    public function __construct($name) {
        parent::__construct($name);
    }

    public function getTitle() {
        return $this->getName()." the geek";
    }
}

$geekObj = new Geek("Ludwig");
$geekObj->sayHello();
$geekObj->sayGoodbye();

यह आउटपुट होगा:

हैलो, मैं geek लुडविग हूँ
व्यक्ति लुडविग से अलविदा

sayHello() $this पॉइंटर का उपयोग करता है, इसलिए Geek::getTitle() को कॉल करने के लिए बुलाया जाता है। sayGoodbye() self::getTitle() sayGoodbye() का उपयोग करता है, इसलिए vtable का उपयोग नहीं किया जाता है, और Person::getTitle() को कॉल किया जाता है। दोनों मामलों में, हम एक तत्काल वस्तु की विधि से निपट रहे हैं, और $this सूचक को कॉल किए गए कार्यों के भीतर $this पॉइंट तक पहुंच है।


इस ब्लॉग पोस्ट से :

  • self वर्तमान वर्ग को संदर्भित करता है
  • self स्थिर कार्यों और संदर्भ स्थिर सदस्य चर को संदर्भित करने के लिए self का उपयोग किया जा सकता है
  • self स्थिर कार्यों के अंदर इस्तेमाल किया जा सकता है
  • self vtable को छोड़कर polymorphic व्यवहार भी बंद कर सकते हैं
  • $this वर्तमान वस्तु को संदर्भित करता है
  • $this स्थिर कार्यों को कॉल करने के लिए इस्तेमाल किया जा सकता है
  • $this स्थिर सदस्य चर कॉल करने के लिए इस्तेमाल नहीं किया जाना चाहिए। इसके बजाए self प्रयोग करें।
  • $this स्थिर कार्यों के अंदर इस्तेमाल नहीं किया जा सकता है

मेरा मानना ​​है कि प्रश्न यह नहीं था कि क्या आप कक्षा ClassName::staticMember को कॉल करके कक्षा के स्थिर सदस्य को कॉल कर सकते हैं। सवाल यह था कि self::classmember और $this->classmember self::classmember का उपयोग करने के बीच क्या अंतर है।

उदाहरण के लिए, निम्न दोनों उदाहरण बिना किसी त्रुटि के काम करते हैं, भले ही आप self:: या $this->

class Person{
    private $name;
    private $address;

    public function __construct($new_name,$new_address){
        $this->name = $new_name;
        $this->address = $new_address;
    }
}

class Person{
    private $name;
    private $address;
    public function __construct($new_name,$new_address){
        self::$name = $new_name;
        self::$address = $new_address;
    }
}




scope