PHP 5 में, उपयोग करने self
और के बीच क्या अंतर है $this
?
प्रत्येक उपयुक्त कब है?
PHP 5 में, उपयोग करने self
और के बीच क्या अंतर है $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
सदस्य कार्यों के लिए:
<?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()
। लेकिन स्वयं के साथ :: फू (),X::foo()
हमेशा कहा जाता है।
से http://www.phpbuilder.com/board/showthread.php?t=10354489 :
Http://board.phpbuilder.com/member.php?145249-laserlight द्वारा
self
गुंजाइश रिज़ॉल्यूशन ऑपरेटर के साथ प्रयोग किया जाता है ::
; यह स्थैतिक और गैर-स्थैतिक दोनों संदर्भों में किया जा सकता है। इसके अतिरिक्त, $this
स्थैतिक तरीकों को कॉल करने के लिए उपयोग करना पूरी तरह से कानूनी है (लेकिन फ़ील्ड को संदर्भित करने के लिए नहीं)।
$this::
?
कीवर्ड सेल्फ केवल 'वर्तमान वर्ग' को संदर्भित नहीं करता है , कम से कम उस तरीके से नहीं जो आपको स्थिर सदस्यों तक सीमित करता है। एक गैर-स्थैतिक सदस्य के संदर्भ में, वर्तमान वस्तु के लिए self
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();
यह आउटपुट होगा:
हेलो, आई एम लुडविग द गीक
गुडबाय फ्रॉम लुडविग द पर्सन
sayHello()
$this
पॉइंटर का उपयोग करता है , इसलिए वाइबेट को कॉल करने के लिए आमंत्रित किया जाता है Geek::getTitle()
।
sayGoodbye()
का उपयोग करता है self::getTitle()
, इसलिए व्यवहार्य उपयोग नहीं किया जाता है, और Person::getTitle()
कहा जाता है। दोनों ही मामलों में, हम एक तात्कालिक वस्तु की विधि के साथ काम कर रहे हैं, और $this
कॉल किए गए कार्यों के भीतर पॉइंटर तक पहुंच है ।
self
में स्थित" / "वर्ग परिभाषा " के रूप में समझा जा सकता है, यह "वस्तु का वर्ग" (जो वास्तव में होगा static
) का एक शाब्दिक हिस्सा है ।
$this::
?
$this::
; सभी संभावित मामलों को पहले से ही आमतौर पर उपयोग किए जाने वाले सिंटैक्स द्वारा कवर किया जाता है। तुम क्या मतलब है के आधार पर, उपयोग $this->
, self::
या static::
।
उपयोग न करें 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()
करने के लिए static::getStatus()
और परिणाम आप क्या उम्मीद करेंगे कर रहे हैं। PHP के पुराने संस्करणों में आपको ऐसा करने के लिए एक कीचड़ ढूंढना होगा।
PHP प्रलेखन देखें
इसलिए पूछे गए सवाल का जवाब नहीं देने के लिए ...
$this->
वर्तमान वस्तु (एक वर्ग का उदाहरण) static::
को संदर्भित करता है , जबकि एक वर्ग को संदर्भित करता है
getStatus
विधि देखता हूं क्योंकि मैं एक वर्ग उदाहरण के लिए कहता हूं, एक वर्ग के लिए नहीं।
self::
, आप इसे प्राप्त कर सकते हैं, कम। भ्रामक रूप से, विशिष्ट वर्ग के नाम का उपयोग करके, जैसे MyClass::
।
वास्तव में यह समझने के लिए कि हम किस बारे में बात कर रहे हैं जब हम self
बनाम के बारे में बात करते हैं $this
, तो हमें वास्तव में एक वैचारिक और व्यावहारिक स्तर पर क्या हो रहा है में खुदाई करने की आवश्यकता है। मैं वास्तव में किसी भी जवाब को उचित रूप से महसूस नहीं करता, इसलिए यहां मेरा प्रयास है।
चलो एक वर्ग और एक वस्तु क्या है के बारे में बात करके शुरू करते हैं ।
तो, एक वर्ग क्या है ? बहुत सारे लोग इसे एक वस्तु के लिए खाका या टेम्पलेट के रूप में परिभाषित करते हैं । वास्तव में, आप 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
$bob instanceof Person
$bob
Person
Person
तो चलिए थोड़ा खुदाई करते हैं कि वास्तव में एक वर्ग क्या है। 5 प्रकार की "चीजें" होती हैं जिनमें एक वर्ग होता है:
गुण - इन्हें चर समझें जो प्रत्येक उदाहरण में होगा।
class Foo {
public $bar = 1;
}
स्टैटिक प्रॉपर्टीज़ - इनको वैरिएबल समझें जो क्लास लेवल पर शेयर की जाती हैं। मतलब कि वे प्रत्येक उदाहरण द्वारा कभी भी कॉपी नहीं किए जाते हैं।
class Foo {
public static $bar = 1;
}
विधियाँ - ये ऐसे कार्य हैं जिनमें प्रत्येक उदाहरण में (और इंस्टेंस पर काम करना) होगा।
class Foo {
public function bar() {}
}
स्टैटिक मेथड्स - ये ऐसे फंक्शन हैं जिन्हें पूरी क्लास में शेयर किया जाता है। वे उदाहरणों पर काम नहीं करते हैं, बल्कि केवल स्थिर गुणों पर।
class Foo {
public static function bar() {}
}
स्थिरांक - वर्ग हल स्थिरांक। यहां कोई गहरा नहीं जा रहा है, लेकिन पूर्णता के लिए जोड़ना:
class Foo {
const BAR = 1;
}
इसलिए मूल रूप से, हम स्थिर के बारे में "संकेत" का उपयोग करके वर्ग और ऑब्जेक्ट कंटेनर पर जानकारी संग्रहीत कर रहे हैं जो यह पहचानता है कि क्या जानकारी साझा की गई है (और इसलिए स्थिर) या नहीं (और इसलिए गतिशील)।
किसी विधि के अंदर, किसी ऑब्जेक्ट का उदाहरण $this
वेरिएबल द्वारा दर्शाया जाता है । उस वस्तु की वर्तमान स्थिति है, और किसी भी संपत्ति को बदलने (बदलने) से उस उदाहरण में परिवर्तन होगा (लेकिन अन्य नहीं)।
यदि किसी विधि को वैधानिक रूप से कहा जाता है, तो $this
चर को परिभाषित नहीं किया जाता है । ऐसा इसलिए है क्योंकि स्टैटिक कॉल के साथ कोई उदाहरण जुड़ा नहीं है।
यहां दिलचस्प बात यह है कि स्थिर कॉल कैसे किए जाते हैं। तो आइए बात करते हैं कि हम राज्य तक कैसे पहुँचें:
इसलिए अब हमने उस स्थिति को संग्रहीत कर लिया है, हमें इसे एक्सेस करने की आवश्यकता है। यह थोड़ा मुश्किल हो सकता है (या थोड़ा से अधिक रास्ता ), तो आइए इसे दो दृष्टिकोणों में विभाजित करें: एक उदाहरण / वर्ग के बाहर (सामान्य फ़ंक्शन कॉल से, या वैश्विक दायरे से), और एक उदाहरण के अंदर। / वर्ग (ऑब्जेक्ट पर एक विधि के भीतर से)।
एक उदाहरण / वर्ग के बाहर से, हमारे नियम काफी सरल और अनुमानित हैं। हमारे पास दो ऑपरेटर हैं, और प्रत्येक तुरंत हमें बताता है कि क्या हम एक उदाहरण या एक स्थिर वर्ग के साथ काम कर रहे हैं:
->
- ऑब्जेक्ट-ऑपरेटर - इसका उपयोग हमेशा तब किया जाता है जब हम किसी इंस्टेंस पर पहुँच रहे हों।
$bob = new Person;
echo $bob->name;
यह ध्यान रखना महत्वपूर्ण है कि कॉलिंग का 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;
}
}
ऑब्जेक्ट-ऑपरेटर का उपयोग करके bar()
विधि $foo
(उदाहरण Foo
) पर कॉल करना : $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
, तो हम इसे एक बच्चे की कक्षा में ओवरराइड कर सकते हैं)।
var_dump($bob->getName()); // Bob
var_dump($adam->getName()); // Adam
var_dump($billy->getName()); // child: Billy
ध्यान दें कि हम हर बार Person::getName()
इंस्टेंस विधि को निष्पादित कर रहे हैं । लेकिन हम parent::getName()
इसे एक मामले (बच्चे के मामले) में करने के लिए उपयोग कर रहे हैं । यह वही है जो इस दृष्टिकोण को शक्तिशाली बनाता है।
ध्यान दें कि यदि उदाहरण का उपयोग किया जाता है तो कॉलिंग संदर्भ निर्धारित करता है। इसलिए:
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
।
यह सभी प्रकार के कीड़े और वैचारिक डब्ल्यूटीएफ-एरि का कारण बन सकता है। तो मैं अत्यधिक परहेज सुझाव देंगे ::
उन तीन आभासी "शॉर्ट कट" कीवर्ड के अलावा कुछ पर उदाहरण के तरीकों के भीतर से ऑपरेटर ( static
, self
, और parent
)।
ध्यान दें कि स्थिर तरीके और गुण सभी द्वारा साझा किए जाते हैं। यह उन्हें मूल रूप से वैश्विक चर बनाता है। ग्लोबल्स के साथ आने वाली सभी समान समस्याओं के साथ। इसलिए मैं वास्तव में स्थिर तरीकों / गुणों में जानकारी संग्रहीत करने में संकोच करूंगा जब तक कि आप इसके साथ सहज नहीं हो जाते जब तक कि यह वास्तव में वैश्विक नहीं हो।
सामान्य तौर पर आप इसका उपयोग करना चाहते हैं जिसे लेट-स्टैटिक-बाइंडिंग के रूप में जाना जाता static
है self
। लेकिन ध्यान दें कि वे एक ही चीज़ नहीं हैं, इसलिए यह कहना कि "हमेशा के static
बजाय उपयोग करना self
वास्तव में अदूरदर्शी है। इसके बजाय, उस कॉल के बारे में रोकें और सोचें जो आप करना चाहते हैं और सोचें कि क्या आप चाहते हैं कि बाल कक्षाएं उस स्थिर समाधान को ओवरराइड करने में सक्षम हों। कहते हैं।
बहुत बुरा, वापस जाओ और इसे पढ़ें। यह बहुत लंबा हो सकता है, लेकिन यह इतना लंबा है क्योंकि यह एक जटिल विषय है
अच्छी बात है। संक्षेप में, एक वर्ग के भीतर वर्तमान वर्ग के नाम को संदर्भित करने के लिए self
उपयोग किया जाता है , जहां वर्तमान वस्तु उदाहरण के रूप में संदर्भित किया जाता है । ध्यान दें कि शॉर्ट-कट एक कॉपी / पेस्ट है। आप इसे सुरक्षित रूप से अपने वर्ग के नाम से बदल सकते हैं, और यह ठीक काम करेगा। लेकिन एक गतिशील चर है जो समय से पहले निर्धारित नहीं किया जा सकता है (और आपकी कक्षा भी नहीं हो सकती है)।$this
self
$this
यदि ऑब्जेक्ट-ऑपरेटर का उपयोग किया जाता है ( ->
), तो आप हमेशा जानते हैं कि आप एक उदाहरण के साथ काम कर रहे हैं। यदि स्कोप-रिज़ॉल्यूशन-ऑपरेटर का उपयोग किया जाता है ( ::
), आपको संदर्भ के बारे में अधिक जानकारी चाहिए (क्या हम ऑब्जेक्ट-संदर्भ में पहले से ही हैं? क्या हम ऑब्जेक्ट के बाहर हैं? आदि)।
$this
परिभाषित नहीं किया जाएगा यदि आप "सख्त मानक" का पालन करते हैं और विधियों को वैधानिक रूप से नहीं कहते हैं जो स्थिर के रूप में परिभाषित नहीं हैं। मैं यहां आपको समझाए गए परिणाम को देखता हूं: 3v4l.org/WeHVM सहमत हैं, वास्तव में अजीब है।
Foo::isFoo()
सांख्यिकीय रूप से कहा जाता है, $this
परिभाषित नहीं किया जाएगा। मेरी राय में यह अधिक सहज व्यवहार है। - एक और अलग परिणाम दिया जाता है अगर Bar
से विस्तार किया गया था Foo
। तब कॉल Foo::isFoo()
वास्तव में उदाहरण के संदर्भ में होगा (PHP7 के लिए विशिष्ट नहीं)।
self
(नहीं $ स्व) वर्ग के प्रकार को $this
संदर्भित करता है , जहां कक्षा की वर्तमान आवृत्ति को संदर्भित करता है । self
स्थैतिक सदस्य कार्यों में उपयोग के लिए है ताकि आप स्थैतिक सदस्य चर का उपयोग कर सकें। $this
गैर-स्थैतिक सदस्य कार्यों में उपयोग किया जाता है, और उस वर्ग के उदाहरण का संदर्भ है जिस पर सदस्य फ़ंक्शन को बुलाया गया था।
क्योंकि this
एक वस्तु है, आप इसका उपयोग करते हैं जैसे:$this->member
क्योंकि self
एक वस्तु नहीं है, यह मूल रूप से एक प्रकार है जो स्वचालित रूप से वर्तमान वर्ग को संदर्भित करता है, आप इसका उपयोग करते हैं:self::member
$this->
एक वर्ग के चर (सदस्य चर) या विधियों के एक विशिष्ट उदाहरण को संदर्भित करने के लिए उपयोग किया जाता है।
Example:
$derek = new Person();
$ derek अब व्यक्ति का एक विशिष्ट उदाहरण है। प्रत्येक व्यक्ति के पास पहले_नाम और अंतिम_नाम है, लेकिन $ derek के पास एक विशिष्ट first_name और last_name (डेरेक मार्टिन) है। $ डेरेक उदाहरण के अंदर, हम उन लोगों को इस $ के रूप में संदर्भित कर सकते हैं-> first_name और $ this-> last_name
ClassName :: का उपयोग उस प्रकार के वर्ग, और उसके स्थिर चर, स्थिर विधियों को संदर्भित करने के लिए किया जाता है। यदि यह मदद करता है, तो आप "स्थिर" शब्द को "साझा" के साथ मानसिक रूप से बदल सकते हैं। क्योंकि वे साझा किए जाते हैं, वे $ इसे संदर्भित नहीं कर सकते, जो एक विशिष्ट उदाहरण (साझा नहीं) को संदर्भित करता है। स्थैतिक चर (यानी स्थिर $ db_connection) को एक प्रकार की वस्तु के सभी उदाहरणों के बीच साझा किया जा सकता है। उदाहरण के लिए, सभी डेटाबेस ऑब्जेक्ट एक कनेक्शन (स्थिर $ कनेक्शन) साझा करते हैं।
स्थैतिक चर उदाहरण: Pretend हमारे पास एक एकल सदस्य चर के साथ एक डेटाबेस वर्ग है: स्थैतिक $ 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 वस्तु के बारे में कुछ भी नहीं जानता है। यह सिर्फ आपके द्वारा पास किए जाने वाले मापदंडों के साथ काम कर रहा है, जैसे कि एक सामान्य फ़ंक्शन जो किसी ऑब्जेक्ट का हिस्सा नहीं है। परेशान क्यों, अगर हम सिर्फ वस्तु के हिस्से के रूप में नहीं कर सकते थे?
SELF :: यदि आप उस ऑब्जेक्ट के बाहर कोडिंग कर रहे हैं जिसमें वह स्थिर विधि है जिसे आप संदर्भित करना चाहते हैं, तो आपको उसे ऑब्जेक्ट के नाम का उपयोग करके कॉल करना होगा देखें :: format_phone_number ($ phone_number); यदि आप उस ऑब्जेक्ट के अंदर कोडिंग कर रहे हैं जिसमें वह स्टैटिक विधि है जिसे आप संदर्भित करना चाहते हैं, तो आप ऑब्जेक्ट के नाम का उपयोग कर सकते हैं देखें :: format_phone_number ($ pn), या आप स्वयं का उपयोग कर सकते हैं :: format_phone_number ($ nn) शॉर्टकट
वही स्थिर वैरिएबल के लिए जाता है: उदाहरण: दृश्य :: टेम्पलेट्स_पथ बनाम स्व :: टेम्पलेट्स_पथ
डीबी वर्ग के अंदर, अगर हम किसी अन्य वस्तु के स्थिर तरीके की बात कर रहे थे, तो हम ऑब्जेक्ट के नाम का उपयोग करेंगे: उदाहरण: सत्र :: getUserOnline ();
लेकिन अगर डीबी वर्ग अपने स्वयं के स्थिर चर को संदर्भित करना चाहता था, तो यह स्वयं कहेगा: उदाहरण: आत्म :: कनेक्शन;
आशा है कि स्पष्ट चीजों में मदद करता है :)
$
संकेत का उपयोग करने की आवश्यकता होती है । उदाहरण के लिएself::$templates_path
से इस ब्लॉग पोस्ट :
self
वर्तमान वर्ग को संदर्भित करता हैself
स्थिर कार्यों और संदर्भ स्थैतिक सदस्य चर को संदर्भित करने के लिए उपयोग किया जा सकता हैself
स्थिर कार्यों के अंदर इस्तेमाल किया जा सकता हैself
विटेबल को दरकिनार करके बहुरूपी व्यवहार को भी बंद कर सकता है$this
वर्तमान वस्तु को संदर्भित करता है$this
स्थिर कार्यों को कॉल करने के लिए इस्तेमाल किया जा सकता है$this
स्थिर सदस्य चर को कॉल करने के लिए उपयोग नहीं किया जाना चाहिए।self
इसके बजाय उपयोग करें ।$this
स्थिर कार्यों के अंदर उपयोग नहीं किया जा सकता है
PHP में, आप स्थैतिक गुणों और विधियों का उपयोग करने के लिए स्व कीवर्ड का उपयोग करते हैं।
समस्या यह है कि आप कहीं $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
उपलब्ध नहीं है, या जब आप वंशजों को वर्तमान पद्धति को अधिलेखित करने की अनुमति नहीं देना चाहते हैं।
एक वर्ग परिभाषा के अंदर, $this
वर्तमान वस्तु को संदर्भित करता है, जबकिself
संदर्भित करता है वर्तमान वर्ग को संदर्भित करता है।
उपयोग करने वाले एक वर्ग तत्व को संदर्भित करना आवश्यक है self
, और उपयोग करने वाले किसी वस्तु तत्व को संदर्भित करना है $this
।
self::STAT // refer to a constant value
self::$stat // static variable
$this->stat // refer to an object variable
Http://www.php.net/manual/en/language.oop5.static.php के अनुसार नहीं है $self
। केवल $this
वर्ग (वस्तु), और स्वयं के वर्तमान उदाहरण का उल्लेख करने के लिए है, जिसका उपयोग किसी वर्ग के स्थिर सदस्यों को संदर्भित करने के लिए किया जा सकता है। एक वस्तु उदाहरण और एक वर्ग के बीच का अंतर यहाँ खेलने में आता है।
मेरा मानना है कि प्रश्न यह नहीं था कि क्या आप कक्षा के स्थिर सदस्य को कॉल करके बता सकते हैं ClassName::staticMember
। सवाल यह था कि उपयोग करने self::classmember
और के बीच अंतर क्या है$this->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;
}
}
Fatal error: Access to undeclared static property: Person::$name in D:\LAMP\www\test.php on line 16
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();
आउटपुट: माता-पिता का बच्चा
$this
वर्तमान ऑब्जेक्ट को संदर्भित करता है।static
वर्तमान वस्तु को संदर्भित करता है।self
तात्पर्य उस सटीक वर्ग से है जिसे इसमें परिभाषित किया गया था।parent
तात्पर्य उस सटीक वर्ग के माता-पिता से है जिसे इसमें परिभाषित किया गया था।निम्नलिखित उदाहरण देखें जो ओवरलोडिंग दिखाता है।
<?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
। हालाँकि, ऐसे समय होते हैं जब आपको आवश्यकता होती है self
क्योंकि आप चाहते हैं कि मूल वर्ग जो चाहे उसे विस्तारित करे। (बहुत, बहुत ही कम)
जैसा कि यहां किसी ने प्रदर्शन के बारे में बात नहीं की, यहां एक छोटा बेंचमार्क है जो मैंने किया था (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();
1 / 2e9 s = 0.5 ns
इन दिनों बनाता है
use
कीवर्ड tbh का उपयोग क्यों नहीं किया है , लेकिन मेरे पास एक बेंचमार्क को फिर से बनाने के लिए PHP नहीं है, और मुझे वास्तव में इसे पुनः स्थापित करने का मन नहीं है।
जब इसे ऑपरेटर के self
साथ उपयोग किया जाता है तो ::
यह वर्तमान वर्ग को संदर्भित करता है, जिसे स्थिर और गैर-स्थिर दोनों संदर्भों में किया जा सकता है। $this
वस्तु को ही संदर्भित करता है। इसके अलावा, $this
स्थैतिक तरीकों को कॉल करने के लिए उपयोग करना पूरी तरह से कानूनी है (लेकिन फ़ील्ड को संदर्भित नहीं करना)।
मैं एक ही सवाल में भाग गया और सरल उत्तर है:
$this
वर्ग के एक उदाहरण की आवश्यकता हैself::
नहीं हैजब भी आप स्थैतिक विधियों या स्थिर विशेषताओं का उपयोग कर रहे हैं और उन्हें तुरंत self:
कॉल करने के लिए उपयोग करने की $this
आवश्यकता है , तो उन्हें तुरंत कॉल करने के लिए उपयोग किए जाने वाले वर्ग की वस्तु के बिना कॉल करना चाहते हैं ।
$this
वर्तमान क्लास ऑब्जेक्ट को self
संदर्भित करता है, वर्तमान क्लास को संदर्भित करता है (ऑब्जेक्ट नहीं)। वर्ग वस्तु का खाका है। तो आप एक वर्ग को परिभाषित करते हैं, लेकिन आप वस्तुओं का निर्माण करते हैं।
तो दूसरे शब्दों में, उपयोग self for static
औरthis for none-static members or methods
।
बच्चे / माता-पिता परिदृश्य में self / parent
भी ज्यादातर बच्चे और माता-पिता वर्ग के सदस्यों और विधियों की पहचान करने के लिए उपयोग किया जाता है।
इसके अतिरिक्त $this::
अभी तक चर्चा नहीं हुई है।
केवल सूचना के प्रयोजनों के लिए, PHP 5.3 के रूप में जब वर्तमान गुंजाइश मान प्राप्त करने के लिए तात्कालिक वस्तुओं के साथ काम कर रहा है, जैसा कि उपयोग करने के लिए विरोध किया जाता है static::
, कोई वैकल्पिक रूप से उपयोग कर सकता $this::
है।
class Foo
{
const NAME = 'Foo';
//Always Foo::NAME (Foo) due to self
protected static $staticName = self::NAME;
public function __construct()
{
echo $this::NAME;
}
public function getStaticName()
{
echo $this::$staticName;
}
}
class Bar extends Foo
{
const NAME = 'FooBar';
/**
* override getStaticName to output Bar::NAME
*/
public function getStaticName()
{
$this::$staticName = $this::NAME;
parent::getStaticName();
}
}
$foo = new Foo; //outputs Foo
$bar = new Bar; //outputs FooBar
$foo->getStaticName(); //outputs Foo
$bar->getStaticName(); //outputs FooBar
$foo->getStaticName(); //outputs FooBar
ऊपर दिए गए कोड का उपयोग करना सामान्य या अनुशंसित अभ्यास नहीं है, लेकिन बस इसके उपयोग को स्पष्ट करना है, और क्या "क्या आप जानते हैं?" मूल पोस्टर के प्रश्न के संदर्भ में।
यह भी $object::CONSTANT
उदाहरण के लिए echo $foo::NAME;
विरोध के रूप में उपयोग का प्रतिनिधित्व करता है$this::NAME;
का प्रयोग करें self
अगर आप उस वर्ग की एक वस्तु / उदाहरण बनाकर बिना एक वर्ग की एक विधि कॉल करने के लिए, इस प्रकार की बचत चाहते रैम (कभी कभी उस उद्देश्य के लिए स्वयं का उपयोग करें)। दूसरे शब्दों में, यह वास्तव में एक विधि को सांख्यिकीय रूप से बुला रहा है। this
ऑब्जेक्ट परिप्रेक्ष्य के लिए उपयोग करें ।
केस 1: का उपयोग self
कक्षा में रहने वालों के लिए किया जा सकता है
क्लास क्लास { const FIXED_NUMBER = 4; स्वयं :: POUNDS_TO_KILOGRAMS }
यदि आप इसे कक्षा के बाहर बुलाना चाहते हैं, तो उपयोग करें classA::POUNDS_TO_KILOGRAMS
तो स्थिरांक का उपयोग करें
केस 2: स्थैतिक गुणों के लिए
क्लास क्लास { सार्वजनिक समारोह __construct () { स्वयं :: $ _ काउंटर ++; $ यह-> संख्या = स्व :: $ _ काउंटर; } }
स्वयं :: वर्तमान वर्ग के लिए उपयोग किया जाने वाला कीवर्ड और मूल रूप से इसका उपयोग स्थैतिक सदस्यों, विधियों और स्थिरांक तक पहुंचने के लिए किया जाता है। लेकिन $ के मामले में आप स्थैतिक सदस्य, विधि और कार्यों को कॉल नहीं कर सकते।
आप किसी अन्य वर्ग में स्व :: कीवर्ड का उपयोग कर सकते हैं और स्थिर सदस्यों, विधि और स्थिरांक का उपयोग कर सकते हैं । जब यह इस कीवर्ड के मामले में मूल वर्ग से समान होगा और समान होगा । आप गैर-स्थिर सदस्यों, विधि और फ़ंक्शन को किसी अन्य वर्ग में एक्सेस कर सकते हैं, जब यह मूल वर्ग से निकाला जाएगा।
नीचे दिया गया कोड स्वयं का एक उदाहरण है :: और इस खोजशब्द $ । बस अपनी कोड फ़ाइल में कोड को कॉपी और पेस्ट करें और आउटपुट देखें।
class cars{
var $doors=4;
static $car_wheel=4;
public function car_features(){
echo $this->doors." Doors <br>";
echo self::$car_wheel." Wheels <br>";
}
}
class spec extends cars{
function car_spec(){
print(self::$car_wheel." Doors <br>");
print($this->doors." Wheels <br>");
}
}
/********Parent class output*********/
$car = new cars;
print_r($car->car_features());
echo "------------------------<br>";
/********Extend class from another class output**********/
$car_spec_show=new spec;
print($car_spec_show->car_spec());