php - सार्वजनिक, निजी और संरक्षित के बीच क्या अंतर है?




oop private (10)

मुझे कक्षा के अंदर public , private और protected कार्यों और चर का उपयोग कब और क्यों करना चाहिए? उनके बीच क्या अंतर है?

उदाहरण:

// Public
public $variable;
public function doSomething() {
  // ...
}

// Private
private $variable;
private function doSomething() {
  // ...
}

// Protected
protected $variable;
protected function doSomething() {
  // ...
}

⚡️ यहां public , protected और private के दायरे को याद रखने का एक आसान तरीका है।

PUBLIC :

  • public दायरा: एक सार्वजनिक चर / समारोह दोनों वस्तुओं और अन्य वर्गों के लिए उपलब्ध है।

PROTECTED :

  • protected दायरा: वर्तमान वर्ग का विस्तार करने वाले सभी वर्गों के लिए एक संरक्षित चर / फ़ंक्शन उपलब्ध है।
  • नहीं! ऑब्जेक्ट्स इस दायरे तक नहीं पहुंच सकते हैं

PRIVATE :

  • private दायरा: एक निजी चर / फ़ंक्शन केवल वर्तमान कक्षा में दिखाई देता है जहां इसे परिभाषित किया जा रहा है।
  • नहीं! कक्षा जो वर्तमान वर्ग का विस्तार करती है, इस दायरे तक नहीं पहुंच सकती है।
  • नहीं! ऑब्जेक्ट्स इस दायरे तक नहीं पहुंच सकते हैं।

PHP मैनुअल पर किसी विधि या चर की http://php.net/manual/en/language.oop5.visibility.php पढ़ें।


'कब' पर विचार करना:
अगर मैं बिल्कुल निश्चित नहीं हूं, तो मैं शुरुआत में निजी रूप से सब कुछ घोषित करता हूं। कारण यह है कि एक निजी विधि को दूसरी तरफ से सार्वजनिक रूप से बदलना आम तौर पर आसान होता है। ऐसा इसलिए है क्योंकि आप कम से कम यह सुनिश्चित कर सकते हैं कि निजी विधि का उपयोग कहीं भी नहीं बल्कि कक्षा में ही किया जा सकता है। एक सार्वजनिक विधि पहले से ही हर जगह उपयोग में हो सकती है, संभवतः एक व्यापक पुनः लिखने की आवश्यकता है।

अपडेट करें: मैं आजकल protected डिफॉल्ट के लिए जाता हूं, क्योंकि मुझे यह पता चला है कि यह encapsulation के लिए पर्याप्त है और जब मैं कक्षाओं का विस्तार कर रहा हूं (जिस तरह से मैं किसी भी तरह से बचने की कोशिश करता हूं) में नहीं मिलता है। केवल अगर मेरे पास दूसरे दो का उपयोग करने का एक अच्छा कारण है, तो मैं करूँगा।

एक private विधि के लिए एक अच्छा कारण वह होगा जो उस वस्तु के निहित कुछ लागू करता है कि यहां तक ​​कि एक विस्तारित वर्ग भी नहीं बदला जाना चाहिए (वास्तविक कारण, encapsulation के अलावा)। आखिरकार, यह ट्रैक करने के लिए अभी भी आसान है कि एक protected विधि का उपयोग आमतौर पर किया जा रहा है, इसलिए मैं आजकल protected करने के लिए डिफ़ॉल्ट हूं। हो सकता है कि 100% उद्देश्य "खाइयों में" अनुभव न हो, मैं मानता हूं।


PHP मैनुअल के प्रश्न पर एक अच्छा पठन http://php.net/manual/en/language.oop5.visibility.php

किसी संपत्ति या विधि की दृश्यता को सार्वजनिक, संरक्षित या निजी कीवर्ड के साथ घोषणा को उपसर्ग करके परिभाषित किया जा सकता है। कक्षा के सदस्यों ने घोषित किया कि जनता को हर जगह पहुंचा जा सकता है। घोषित सदस्यों को संरक्षित किया जा सकता है केवल कक्षा के भीतर और वंचित और अभिभावक वर्गों द्वारा ही। सदस्यों को निजी घोषित किया जा सकता है केवल सदस्य द्वारा परिभाषित किया जा सकता है जो सदस्य को परिभाषित करता है।


अंतर इस प्रकार है:

Public :: वर्ग के किसी भी उपयोगकर्ता द्वारा सीधे सार्वजनिक चर या विधि का उपयोग किया जा सकता है।

Protected :: वर्ग के उपयोगकर्ताओं द्वारा संरक्षित चर या विधि तक पहुंचा नहीं जा सकता है लेकिन कक्षा से प्राप्त होने वाले उप-वर्ग के अंदर पहुंचा जा सकता है।

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


एक पुराने सवाल को पुनर्जीवित करना, लेकिन मुझे लगता है कि इस बारे में सोचने का एक अच्छा तरीका एपीआई के संदर्भ में है जिसे आप परिभाषित कर रहे हैं।

  • public - सब कुछ चिह्नित चिह्नित एपीआई का हिस्सा है कि आपकी कक्षा / इंटरफेस / अन्य का उपयोग करने वाले किसी भी व्यक्ति का उपयोग और भरोसा होगा।

  • protected - मूर्ख मत बनो, यह एपीआई का भी हिस्सा है! लोग उप-वर्गीकरण कर सकते हैं, अपना कोड बढ़ा सकते हैं और सुरक्षित चिह्नित कुछ भी इस्तेमाल कर सकते हैं।

  • private - जितनी चाहें उतनी निजी संपत्तियों और विधियों को बदला जा सकता है। कोई और इनका उपयोग नहीं कर सकता है। ये एकमात्र चीजें हैं जिन्हें आप परिवर्तनों को तोड़ने के बिना बदल सकते हैं।

या Semver शब्दों में:

  • public या protected किसी भी चीज़ में परिवर्तनों को बड़े बदलावों के रूप में माना जाना चाहिए।

  • कुछ भी नया public या protected होना चाहिए (कम से कम) MINOR

  • private पर कुछ भी नया / परिवर्तन पैच हो सकता है

इसलिए कोड बनाए रखने के मामले में, यह सुनिश्चित करना अच्छा होता है कि आप जो चीजें public या protected करते हैं, क्योंकि ये वे चीजें हैं जिन्हें आप अपने उपयोगकर्ताओं के लिए वादा कर रहे हैं।


तुम इस्तेमाल:

  • उस चर / समारोह को कहीं भी, ऑब्जेक्ट के अन्य वर्गों और उदाहरणों से उपलब्ध करने के लिए public दायरा।

  • जब आप अपना चर / फ़ंक्शन केवल अपनी कक्षा में दिखाना चाहते हैं तो private दायरा।

  • protected दायरा जब आप अपने वर्ग / फ़ंक्शन को उन सभी वर्गों में दृश्यमान बनाना चाहते हैं जो वर्तमान वर्ग को मूल वर्ग समेत विस्तारित करते हैं।

अधिक: (व्यापक जानकारी के लिए)


मेरे लिए, यह तीन संपत्ति प्रकारों को समझने का सबसे उपयोगी तरीका है:

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

कक्षा के बाहर से उदाहरण का उपयोग:

$myObject = new MyObject()
$myObject->publicVar = 'newvalue';
$pubVar = $myObject->publicVar;

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

क्यूं कर? क्योंकि यदि आप भविष्य में किसी बिंदु पर निर्णय लेते हैं (शायद 5 मिनट की तरह) कि आप उस संपत्ति के लिए लौटाए गए मूल्य में हेरफेर करना चाहते हैं या प्राप्त करने से पहले इसके साथ कुछ करना चाहते हैं, तो आप इसे हर जगह रीफैक्टरिंग के बिना कर सकते हैं इसे अपने प्रोजेक्ट में इस्तेमाल किया।

कक्षा के बाहर से उदाहरण का उपयोग:

$myObject = new MyObject()
$myObject->setProtectedVar('newvalue');
$protectedVar = $myObject->getProtectedVar();

निजी : private गुण protected गुणों के समान हैं। लेकिन विशिष्ट विशेषता / अंतर यह है कि इसे private बनाने से माता-पिता वर्ग के गेटटर या सेटर का उपयोग किए बिना बाल कक्षाओं में पहुंच योग्य हो जाता है।

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

एक बाल वर्ग के अंदर उदाहरण का उपयोग (जो MyObject को बढ़ाता है):

$this->setPrivateVar('newvalue');
$privateVar = $this->getPrivateVar();

वे encapsulation विभिन्न स्तरों के लिए अनुमति देने के लिए वहाँ हैं


सार उदाहरणों के साथ दृश्यता क्षेत्र :: समझना आसान बनाता है

किसी संपत्ति या विधि की यह दृश्यता तीन कीवर्ड (सार्वजनिक, संरक्षित और निजी) में से एक की पूर्व-निर्धारण घोषणा द्वारा परिभाषित की जाती है।

सार्वजनिक : यदि किसी संपत्ति या विधि को जनता के रूप में परिभाषित किया गया है, तो इसका मतलब है कि यह ऑब्जेक्ट को संदर्भित करने वाले किसी भी चीज़ द्वारा एक्सेस और हेरफेर किया जा सकता है।

  • सार उदा। "सार्वजनिक पिकनिक" के रूप में सार्वजनिक दृश्यता के दायरे को सोचें कि कोई भी आ सकता है।

संरक्षित: जब किसी संपत्ति या विधि दृश्यता को संरक्षित सदस्यों पर सेट किया जाता है, तो केवल कक्षा के भीतर ही और वंचित और विरासत कक्षाओं तक पहुंच हो सकती है। (विरासत: - एक वर्ग में सभी गुणों और अन्य वर्गों के तरीकों हो सकते हैं)।

  • "कंपनी पिकनिक" के रूप में संरक्षित दृश्यता के रूप में सोचें जहां कंपनी के सदस्यों और उनके परिवार के सदस्यों को जनता की अनुमति नहीं है। यह सबसे आम दायरा प्रतिबंध है।

निजी: जब कोई संपत्ति या विधि दृश्यता निजी पर सेट की जाती है, तो केवल उस कक्षा में निजी सदस्य होते हैं, जो क्लास रिलेशनशिप के बावजूद उन विधियों और गुणों (आंतरिक रूप से कक्षा के भीतर) तक पहुंच सकते हैं।

  • पिकनिक सादृश्य के साथ पिकनिक में "कंपनी पिकनिक जहां केवल कंपनी के सदस्यों की अनुमति है" के रूप में सोचते हैं । परिवार नहीं, न ही आम जनता की अनुमति है।

जनता:

जब आप किसी विधि (फ़ंक्शन) या किसी संपत्ति (चर) को public रूप में घोषित करते हैं, तो उन विधियों और गुणों का उपयोग इस तक किया जा सकता है:

  • वही वर्ग जिसने इसे घोषित किया।
  • उपरोक्त घोषित कक्षा के उत्तराधिकारी वर्ग।
  • इस वर्ग के बाहर कोई भी विदेशी तत्व उन चीजों तक भी पहुंच सकता है।

उदाहरण:

<?php

class GrandPa
{
    public $name='Mark Henry';  // A public variable
}

class Daddy extends GrandPa // Inherited class
{
    function displayGrandPaName()
    {
        return $this->name; // The public variable will be available to the inherited class
    }

}

// Inherited class Daddy wants to know Grandpas Name
$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'

// Public variables can also be accessed outside of the class!
$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Prints 'Mark Henry'

संरक्षित:

जब आप एक विधि (फ़ंक्शन) या एक संपत्ति (चर) को protected रूप में घोषित करते हैं, तो उन विधियों और गुणों तक पहुंचा जा सकता है

  • वही वर्ग जिसने इसे घोषित किया।
  • उपरोक्त घोषित कक्षा के उत्तराधिकारी वर्ग।

बाहरी सदस्य उन चरों तक नहीं पहुंच सकते हैं। "आउटसाइडर्स" इस अर्थ में कि वे घोषित कक्षा के ऑब्जेक्ट्स ऑब्जेक्ट्स नहीं हैं

उदाहरण:

<?php

class GrandPa
{
    protected $name = 'Mark Henry';
}

class Daddy extends GrandPa
{
    function displayGrandPaName()
    {
        return $this->name;
    }

}

$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Prints 'Mark Henry'

$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error

सटीक त्रुटि यह होगी:

PHP घातक त्रुटि: संरक्षित संपत्ति GrandPa :: $ name तक नहीं पहुंच सकता है

निजी:

जब आप एक विधि (फ़ंक्शन) या एक संपत्ति (चर) को private रूप में घोषित करते हैं, तो उन विधियों और गुणों का उपयोग इस तक किया जा सकता है:

  • वही वर्ग जिसने इसे घोषित किया।

बाहरी सदस्य उन चरों तक नहीं पहुंच सकते हैं। बाहरी लोगों को इस अर्थ में कि वे घोषित वर्ग के ऑब्जेक्ट्स और यहां तक ​​कि कक्षाओं को घोषित कक्षा के उत्तराधिकारी के उदाहरण नहीं हैं

उदाहरण:

<?php

class GrandPa
{
    private $name = 'Mark Henry';
}

class Daddy extends GrandPa
{
    function displayGrandPaName()
    {
        return $this->name;
    }

}

$daddy = new Daddy;
echo $daddy->displayGrandPaName(); // Results in a Notice 

$outsiderWantstoKnowGrandpasName = new GrandPa;
echo $outsiderWantstoKnowGrandpasName->name; // Results in a Fatal Error

सटीक त्रुटि संदेश होंगे:

नोटिस: अपरिभाषित संपत्ति: डैडी :: $ नाम
घातक त्रुटि: निजी संपत्ति GrandPa :: $ name तक नहीं पहुंच सकता है

Reflection का उपयोग करते Reflection दादा वर्ग को विच्छेदन करना

यह विषय वास्तव में दायरे से बाहर नहीं है, और मैं इसे साबित करने के लिए यहां जोड़ रहा हूं कि प्रतिबिंब वास्तव में शक्तिशाली है। जैसा कि मैंने उपर्युक्त तीन उदाहरणों में कहा था, protected और private सदस्यों (गुणों और विधियों) को कक्षा के बाहर नहीं पहुंचा जा सकता है।

हालांकि, प्रतिबिंब के साथ आप कक्षा के बाहर protected और private सदस्यों तक पहुंचने के द्वारा अतिरिक्त-साधारण कर सकते हैं!

खैर, प्रतिबिंब क्या है?

प्रतिबिंब कक्षाओं, इंटरफेस, कार्यों, विधियों और एक्सटेंशन को रिवर्स-इंजीनियर करने की क्षमता को जोड़ता है। इसके अतिरिक्त, वे कार्यों, कक्षाओं और विधियों के लिए दस्तावेज़ टिप्पणियों को पुनर्प्राप्त करने के तरीके प्रदान करते हैं।

प्रस्तावना

हमारे पास Grandpas नामक एक वर्ग है और कहें कि हमारे पास तीन गुण हैं। आसान समझ के लिए, विचार करें कि नाम के साथ तीन दादा हैं:

  • मार्क हेनरी
  • जॉन टकराव
  • जोन्स होगा

आइए हम उन्हें क्रमशः public , protected और private बनाते हैं (संशोधक असाइन करें)। आप बहुत अच्छी तरह से जानते हैं कि protected और private सदस्यों को कक्षा के बाहर नहीं पहुंचा जा सकता है। अब प्रतिबिंब का उपयोग करके बयान का खंडन करते हैं।

कोड

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected  modifier
    private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
}


# Scenario 1: without reflection
$granpaWithoutReflection = new GrandPas;

# Normal looping to print all the members of this class
echo "#Scenario 1: Without reflection<br>";
echo "Printing members the usual way.. (without reflection)<br>";
foreach($granpaWithoutReflection as $k=>$v)
{
    echo "The name of grandpa is $v and he resides in the variable $k<br>";
}

echo "<br>";

#Scenario 2: Using reflection

$granpa = new ReflectionClass('GrandPas'); // Pass the Grandpas class as the input for the Reflection class
$granpaNames=$granpa->getDefaultProperties(); // Gets all the properties of the Grandpas class (Even though it is a protected or private)


echo "#Scenario 2: With reflection<br>";
echo "Printing members the 'reflect' way..<br>";

foreach($granpaNames as $k=>$v)
{
    echo "The name of grandpa is $v and he resides in the variable $k<br>";
}

आउटपुट:

#Scenario 1: Without reflection
Printing members the usual way.. (Without reflection)
The name of grandpa is Mark Henry and he resides in the variable name1

#Scenario 2: With reflection
Printing members the 'reflect' way..
The name of grandpa is Mark Henry and he resides in the variable name1
The name of grandpa is John Clash and he resides in the variable name2
The name of grandpa is Will Jones and he resides in the variable name3

आम गलतफहमी:

कृपया नीचे दिए गए उदाहरण से भ्रमित न हों। जैसा कि आप अभी भी देख सकते हैं, private और protected सदस्यों को प्रतिबिंब का उपयोग किए बिना कक्षा के बाहर नहीं पहुंचा जा सकता है

<?php

class GrandPas   // The Grandfather's class
{
    public     $name1 = 'Mark Henry';  // This grandpa is mapped to a public modifier
    protected  $name2 = 'John Clash';  // This grandpa is mapped to a protected modifier
    private    $name3 = 'Will Jones';  // This grandpa is mapped to a private modifier
}

$granpaWithoutReflections = new GrandPas;
print_r($granpaWithoutReflections);

आउटपुट:

GrandPas Object
(
    [name1] => Mark Henry
    [name2:protected] => John Clash
    [name3:GrandPas:private] => Will Jones
)

डिबगिंग फ़ंक्शन

print_r , var_export और var_dump डीबगर फ़ंक्शन हैं । वे मानव-पठनीय रूप में एक चर के बारे में जानकारी प्रस्तुत करते हैं। ये तीन कार्य PHP 5 के साथ वस्तुओं के protected और private गुणों को प्रकट करेंगे। स्टेटिक क्लास के सदस्यों को नहीं दिखाया जाएगा।

और अधिक संसाधनों:





protected