गेटटर और सेटर?


203

मैं एक PHP डेवलपर नहीं हूं, इसलिए मैं सोच रहा हूं कि क्या PHP एक शुद्ध ओओपी शैली में, स्पष्ट फ़ील्ड / सेटर का उपयोग करने के लिए अधिक लोकप्रिय है, निजी क्षेत्रों के साथ (जैसा मुझे पसंद है):

class MyClass {
    private $firstField;
    private $secondField;

    public function getFirstField() {
        return $this->firstField;
    }
    public function setFirstField($x) {
        $this->firstField = $x;
    }
    public function getSecondField() {
        return $this->secondField;
    }
    public function setSecondField($x) {
        $this->secondField = $x;
    }
}

या सिर्फ सार्वजनिक क्षेत्र:

class MyClass {
    public $firstField;
    public $secondField;
}

धन्यवाद


7
उत्तरों में से कुछ कोड को आज़माने के बाद मैंने उस कोड का उपयोग किया जो आप प्रश्न में उपयोग कर रहे हैं। कितना दुखद :-(
1

9
PHPstorm ... उत्पन्न> गेटर्स और सेटर्स। == जीत
DevDonkey

@DevDonkey एक जीत नहीं है। संरचित डेटा रखने के लिए, इसके बजाय सरणियों का उपयोग करें। @: मार्क यह नहीं है कि ऑब्जेक्ट क्या हैं या किसके लिए हैं। गेटर्स और सेटर
Kubo2

जवाबों:


222

आप php मैजिक विधियों का उपयोग कर सकते हैं __getऔर __set

<?php
class MyClass {
  private $firstField;
  private $secondField;

  public function __get($property) {
    if (property_exists($this, $property)) {
      return $this->$property;
    }
  }

  public function __set($property, $value) {
    if (property_exists($this, $property)) {
      $this->$property = $value;
    }

    return $this;
  }
}
?>

15
मुझे लगता है कि आप का मतलब है __getऔर __set। दो अंडरस्कोर हैं, एक नहीं। यहाँ पृष्ठ के दाहिने भाग का सीधा लिंक दिया गया है: php.net/manual/en/… (एक सही उत्तर के लिए +1)
Computerish

28
publicयदि कोई मान्यता / स्वच्छता नहीं है, तो संपत्तियों के खिलाफ लाभ प्राप्त करें ?
KingCrunch

7
@KingCrunch, यह सिर्फ एक उदाहरण है। एक शक्तिशाली संसाधन के लिए बहुत बहुत डमी उदाहरण।
डेविस पीक्सोटो

10
यह वास्तव में सेटर और गटर नहीं है। आमतौर पर मुझे प्रत्येक संपत्ति के लिए गटर के अलग-अलग कार्यान्वयन की आवश्यकता होती है!
sumid

79
कृपया नहीं: जादू के तरीकों से आप कई IDE (यहां तक ​​कि विम) में लगभग हर गुणवत्ता-संबंधित सुविधाओं को खो देंगे: स्वतः पूर्णता, स्पष्ट PHP उत्तराधिकार, तेज़ PHP व्याख्या और उपयोगी PHPDoc पीढ़ी और आउटपुट। सीएफ stackoverflow.com/a/6184893/490589
रॉनन

113

गेटर्स और सेटर का उपयोग क्यों करें?

  1. स्केलेबिलिटी : प्रोजेक्ट कोड में सभी वर्जन असाइनमेंट को सर्च करने की तुलना में यह आसान रिफ्लेक्टर है।
  2. डिबगिंग : आप बसने और पाने वालों में ब्रेकपॉइंट लगा सकते हैं।
  3. क्लीनर : जादू कम करने के लिए अच्छे कार्य नहीं हैं, आपका आईडीई कोड का सुझाव नहीं देगा। फास्ट-राइटिंग गेटर्स के लिए बेहतर उपयोग टेम्पलेट।

प्रत्यक्ष असाइनमेंट और गेटर्स / सेटर


7
यदि आप @property का उपयोग करते हैं, तो आपका IDE कोड सुझाएगा (
PhpStorm

41

Google ने पहले ही PHP के अनुकूलन पर एक गाइड प्रकाशित किया था और निष्कर्ष था:

कोई गेट्टर और सेटर ऑप्टिमाइज़िंग PHP नहीं

और नहीं, आपको जादू के तरीकों का उपयोग नहीं करना चाहिए । PHP के लिए, मैजिक मेथड बुराई है। क्यों?

  1. वे डीबग करना कठिन है।
  2. एक नकारात्मक प्रदर्शन प्रभाव है।
  3. उन्हें अधिक कोड लिखने की आवश्यकता है।

PHP जावा, C ++ या C # नहीं है। PHP अलग है और विभिन्न भूमिकाओं के साथ खेलता है।


10
मैं उस विचार से सहमत हूं; कि $dog->name = 'fido'तुलना में बेहतर है $dog->setName('fido')। जब वास्तव में एक संपत्ति को उत्परिवर्तित करना (पूर्व: $dog->increaseAge(1)मैं उस विधि का निर्माण कर सकता हूं जो आवश्यक सत्यापन करता है और उस संपत्ति को उत्परिवर्तित करता है। लेकिन सभी कार्यों को वास्तव में उस अर्थ में उत्परिवर्तन की आवश्यकता नहीं होती है।
चार्ली श्लीसेर

11
लेख " नहीं " नहीं कहता है , यह कहता है कि 'भोले वासियों और गेटर्स'।
ब्रेट सैंटोर

1
इसे पुनर्जीवित किया गया है: web.archive.org/web/20140625191431/https://…

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

3
यह कहना है कि इनलाइन स्टाइल बेहतर है। बेशक प्रदर्शन बेहतर है, लेकिन क्या यह बेहतर कोड है? मुझे नहीं पता था कि गूगल के इंजीनियर वैसे भी php का इस्तेमाल करते हैं
Claudiu Creanga

13

किसी भी ओओ भाषा में एनकैप्सुलेशन महत्वपूर्ण है, लोकप्रियता का इससे कोई लेना-देना नहीं है। PHP की तरह गतिशील रूप से टाइप की जाने वाली भाषाओं में, यह विशेष रूप से उपयोगी है क्योंकि यह सुनिश्चित करने के लिए बहुत कम तरीके हैं कि कोई संपत्ति एक विशिष्ट प्रकार का है जो कि बसने वालों का उपयोग किए बिना है।

PHP में, यह काम करता है:

class Foo {
   public $bar; // should be an integer
}
$foo = new Foo;
$foo->bar = "string";

जावा में, यह नहीं है:

class Foo {
   public int bar;
}
Foo myFoo = new Foo();
myFoo.bar = "string"; // error

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


7
गेटर्स और सेटर इनकैप्सुलेशन नहीं लाते हैं। एनकैप्सुलेशन == वस्तुएं अपने डेटा के साथ कुछ करती हैं बजाय उन्हें बाहर देने के। PHP की तरह गतिशील भाषाओं में टाइप करने के लिए गेटर्स और सेटर एक उपकरण नहीं हैं।
रात 11:54

14
@ सिमेंटेक: आप स्पष्ट रूप से कम से कम आधे से गायब हैं कि वास्तव में इनकैप्सुलेशन क्या है।
netcoder

2
किसी को भी देखने के लिए इस अद्यतन के रूप में, PHP 7.4 टाइप संपत्ति के समर्थन के साथ आएगा। यदि आप यह घोषणा कर सकता है तो $barएक के रूप में int: पहले उदाहरण में wiki.php.net/rfc/typed_properties_v2
केविन

7

यदि आप __call फ़ंक्शन का उपयोग करने के लिए प्राथमिकता देते हैं, तो आप इस पद्धति का उपयोग कर सकते हैं। इसके साथ काम करता है

  • प्राप्त => $this->property()
  • सेट => $this->property($value)
  • प्राप्त => $this->getProperty()
  • सेट => $this->setProperty($value)

kalsdas

public function __call($name, $arguments) {

    //Getting and setting with $this->property($optional);

    if (property_exists(get_class($this), $name)) {


        //Always set the value if a parameter is passed
        if (count($arguments) == 1) {
            /* set */
            $this->$name = $arguments[0];
        } else if (count($arguments) > 1) {
            throw new \Exception("Setter for $name only accepts one parameter.");
        }

        //Always return the value (Even on the set)
        return $this->$name;
    }

    //If it doesn't chech if its a normal old type setter ot getter
    //Getting and setting with $this->getProperty($optional);
    //Getting and setting with $this->setProperty($optional);
    $prefix = substr($name, 0, 3);
    $property = strtolower($name[3]) . substr($name, 4);
    switch ($prefix) {
        case 'get':
            return $this->$property;
            break;
        case 'set':
            //Always set the value if a parameter is passed
            if (count($arguments) != 1) {
                throw new \Exception("Setter for $name requires exactly one parameter.");
            }
            $this->$property = $arguments[0];
            //Always return the value (Even on the set)
            return $this->$name;
        default:
            throw new \Exception("Property $name doesn't exist.");
            break;
    }
}

2
@ krzysztof-przygoda: यह "मैजिक मेथड्स" हमेशा एक मूल्य के साथ आता है। उन्हें पुनरावर्तन का उपयोग करना पड़ता है property_exists(get_class($this), $name)और पुनरावृत्ति धीमी होती है। कैशिंग के साथ इसे कम करने का एक तरीका y है, लेकिन यह अभी भी हाथ से गेटर्स और सेटर बनाने की तुलना में धीमा होने वाला है। मैंने इसे केवल एक विकल्प के रूप में लिखा था। मैं वास्तव में "मैजिक मेथड्स" का उपयोग करने की सलाह नहीं देता। गेटर्स और सेटर बनाने का अतिरिक्त समय आमतौर पर महत्वहीन होता है।
जे-रौ

7

यहाँ पहले से ही महान और सम्मानित जवाबों के अलावा, मैं PHP पर विस्तार करना चाहूँगा जिसमें कोई बसने / पाने वाले न हों।

PHP में गेट्टर और सेटर सिंटैक्स नहीं होता है । यह"हुकिंग" की अनुमति देने के लिएउपवर्गित या जादू के तरीकेप्रदान करता हैऔर दवे द्वारा बताई गई संपत्ति देखने की प्रक्रिया को ओवरराइड करता है।

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

प्रदर्शन हर अनावश्यक फ़ंक्शन, जो कि PHP में एक गेट्टर / सेटर-जैसे कोड-आर्किटेक्चर को मजबूर करने के परिणामस्वरूप होता है, इसमें शामिल होने पर अपनी मेमोरी स्टैक-फ्रेम शामिल होती है और सीपीयू चक्रों को बर्बाद कर रहा है।

पठनीयता: कोडबेस में ब्लोटिंग कोड-लाइनें होती हैं, जो कोड-नेविगेशन को प्रभावित करती हैं क्योंकि LOC का अर्थ है अधिक स्क्रॉलिंग,।

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

भ्रम:

एक सामान्य तर्क पठनीयता है। उदाहरण के लिए, $someobject->widthपढ़ने में आसान है $someobject->width()। हालांकि विपरीत एक ग्रह के circumferenceया width, माना जा सकता है जो होने के लिए static, इस तरह के रूप एक वस्तु के उदाहरण $someobjectहै, जो एक चौड़ाई समारोह की आवश्यकता है, संभावना वस्तु के उदाहरण चौड़ाई का एक माप लेता है।
इसलिए मुखर नामकरण-योजनाओं के कारण पठनीयता मुख्य रूप से बढ़ जाती है, न कि उस फ़ंक्शन को छिपाकर जो किसी दिए गए संपत्ति-मूल्य को आउटपुट करता है।

__get / __set उपयोग करता है:

  • पूर्व-मान्यता और संपत्ति मूल्यों की पूर्व-स्वच्छता

  • तार जैसे

    "
    some {mathsobj1->generatelatex} multi
    line text {mathsobj1->latexoutput}
    with lots of variables for {mathsobj1->generatelatex}
     some reason
    "

    इस मामले generatelatexमें एक्शन नाम + मेथडनाम की नामकरण योजना का पालन करना होगा

  • विशेष, स्पष्ट मामले

    $dnastringobj->homeobox($one_rememberable_parameter)->gattaca->findrelated()
    $dnastringobj->homeobox($one_rememberable_parameter)->gttccaatttga->findrelated()

नोट: PHP ने गेटटर / सेटर सिंटैक्स को लागू नहीं करने के लिए चुना। मैं यह दावा नहीं कर रहा हूं कि गेटर्स / सेटर आमतौर पर खराब होते हैं।


6
class MyClass {
    private $firstField;
    private $secondField;
    private $thirdField;

    public function __get( $name ) {
        if( method_exists( $this , $method = ( 'get' . ucfirst( $name  ) ) ) )
            return $this->$method();
        else
            throw new Exception( 'Can\'t get property ' . $name );
    }

    public function __set( $name , $value ) {
        if( method_exists( $this , $method = ( 'set' . ucfirst( $name  ) ) ) )
            return $this->$method( $value );
        else
            throw new Exception( 'Can\'t set property ' . $name );
    }

    public function __isset( $name )
    {
        return method_exists( $this , 'get' . ucfirst( $name  ) ) 
            || method_exists( $this , 'set' . ucfirst( $name  ) );
    }

    public function getFirstField() {
        return $this->firstField;
    }

    protected function setFirstField($x) {
        $this->firstField = $x;
    }

    private function getSecondField() {
        return $this->secondField;
    }
}

$obj = new MyClass();

echo $obj->firstField; // works
$obj->firstField = 'value'; // works

echo $obj->getFirstField(); // works
$obj->setFirstField( 'value' ); // not works, method is protected

echo $obj->secondField; // works
echo $obj->getSecondField(); // not works, method is private

$obj->secondField = 'value'; // not works, setter not exists

echo $obj->thirdField; // not works, property not exists

isset( $obj->firstField ); // returns true
isset( $obj->secondField ); // returns true
isset( $obj->thirdField ); // returns false

तैयार!


बहुत अधिक बॉयलरप्लेट। कल्पना कीजिए कि यह सामान हर वर्ग में है। IMO से बचें
DarkNeuron

PHP आपके द्वारा उल्लिखित समान कारणों के लिए गेटर्स और सेटर का समर्थन नहीं करता है। इस प्रकार का कोई भी कार्यान्वयन सर्वर-साइड स्क्रिप्ट के प्रदर्शन को गंभीर रूप से प्रभावित करता है।
जोस

मुझे लगता है कि यह 'निजी' गुणों के खिलाफ है। आप उन्हें एनकैप्सुलेट करते हैं, लेकिन सीधे पहुंच की भी अनुमति देते हैं।
कोरे कुपेपे

@ KorayKüpe केवल अगर गेटर को परिभाषित किया गया है। मैं इस एनकैप्सुलेशन का बहुत उपयोग करता हूं (कई सुधारों के साथ) और यह पूरी तरह से काम करता है। आप वर्ग का विस्तार भी कर सकते हैं और आसानी से सभी कोड में इसका उपयोग कर सकते हैं।
जोस

5

खैर, पीएचपी जादू तरीकों है __get, __set, __issetऔर __unsetहै, जो हमेशा एक शुरुआत है। अलास उचित (इसे प्राप्त करें?) ओओ गुण जादू विधियों की तुलना में अधिक है। PHP के कार्यान्वयन के साथ मुख्य समस्या यह है कि सभी दुर्गम गुणों के लिए जादू के तरीकों को बुलाया जाता है । जिसका अर्थ है कि आपको जादू विधियों में प्रॉपर्टी_एक्सिस्ट्स () कॉल करके अपने आप को दोहराना होगा (यह निर्धारित करते समय कि नाम वास्तव में आपके ऑब्जेक्ट की संपत्ति है। और आप वास्तव में इस सामान्य समस्या को आधार वर्ग के साथ हल नहीं कर सकते हैं जब तक कि आपकी सभी कक्षाएं विरासत में नहीं मिलतीं। ClassWithProperties, चूंकि PHP में कई वंशानुक्रम का अभाव है।

इसके विपरीत, पायथन नई शैली की कक्षाएं आपको देता है property(), जो आपको स्पष्ट रूप से आपके सभी गुणों को परिभाषित करने देता है। C # में विशेष वाक्य रचना है।

http://en.wikipedia.org/wiki/Property_(programming)


1
एक रनटाइम घातक त्रुटि से बचने के लिए प्रॉपर्टी_एक्सिस्ट्स, क्लास_वार्स या अरेंज_की_एक्सिस्ट्स (यानी, अगर प्रॉपर्टी वास्तव में मौजूद है) को कॉल करना केवल एक कदम है। मुझे यकीन नहीं है कि अगर विस्थापित होना कोडिंग में दोहराव के समान नहीं है।
डेविस पीक्सोटो

1
काफी उचित। लेकिन अजगर और सी # में इस पुनरावृत्ति की आवश्यकता नहीं है। मुझे लगता है कि यह एक ताकत है।
इमानुएल लैंडहोम

4

मैंने जादू की विधि __call का उपयोग करके एक प्रयोग किया। निश्चित नहीं है कि मुझे इसे पोस्ट करना चाहिए (सभी जवाबों और टिप्पणियों में चेतावनी के कारण "सभी का उपयोग न करें" लेकिन मैं इसे यहां छोड़ दूँगा .. यदि कोई व्यक्ति इसे उपयोगी पाता है।


public function __call($_name, $_arguments){
    $action  = substr($_name, 0, 4);
    $varName = substr($_name, 4);

    if (isset($this->{$varName})){
        if ($action === "get_") return $this->{$varName};
        if ($action === "set_") $this->{$varName} = $_arguments[0];
    }
}

अपनी कक्षा में उपरोक्त विधि जोड़ें, अब आप टाइप कर सकते हैं:

class MyClass{
    private foo = "bar";
    private bom = "bim";
    // ...
    // public function __call(){ ... }
    // ...
}
$C = new MyClass();

// as getter
$C->get_foo(); // return "bar"
$C->get_bom(); // return "bim"

// as setter
$C->set_foo("abc"); // set "abc" as new value of foo
$C->set_bom("zam"); // set "zam" as new value of bom


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

उदाहरण:

private $callWhiteList = array(
    "foo" => "foo",
    "fee" => "fee",
    // ...
);

public function __call($_name, $_arguments){
    $action  = substr($_name, 0, 4);
    $varName = $this->callWhiteList[substr($_name, 4)];

    if (!is_null($varName) && isset($this->{$varName})){
        if ($action === "get_") return $this->{$varName};
        if ($action === "set_") $this->{$varName} = $_arguments[0];
    }
}

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

private $callWhiteList = array(
    "myfoo" => "foo",
    "zim" => "bom",
    // ...
);

उस सूची के साथ अब आप टाइप कर सकते हैं:

class MyClass{
    private foo = "bar";
    private bom = "bim";
    // ...
    // private $callWhiteList = array( ... )
    // public function __call(){ ... }
    // ...
}
$C = new MyClass();

// as getter
$C->get_myfoo(); // return "bar"
$C->get_zim(); // return "bim"

// as setter
$C->set_myfoo("abc"); // set "abc" as new value of foo
$C->set_zim("zam"); // set "zam" as new value of bom




बस इतना ही।


Doc: __call () ऑब्जेक्ट संदर्भ में दुर्गम विधियों को लागू करते समय ट्रिगर किया जाता है।


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

2

अन्य सलाह पढ़ने के बाद, मैं यह कहना चाहूंगा कि:

एक सामान्य नियम के रूप में, आप हमेशा सभी गुणों के लिए बसने वालों को परिभाषित नहीं करेंगे , विशेष रूप से "आंतरिक" वाले (अर्ध-आंतरिक, आंतरिक झंडे ...)। केवल-पढ़ने के गुणों में बसने वाले नहीं होंगे, जाहिर है, इसलिए कुछ गुणों में केवल गेटर्स होंगे; यह वह जगह है जहाँ __get () कोड सिकुड़ने के लिए आता है:

  • उन सभी संपत्तियों के लिए एक __get () (जादुई वैश्विक गेटर्स) परिभाषित करें जो समान हैं,
  • उन्हें सरणियों में समूहित करें:
    • वे सामान्य विशेषताओं को साझा करेंगे: मौद्रिक मूल्य ठीक से स्वरूपित होंगे, एक विशिष्ट लेआउट में तिथियां (आईएसओ, यूएस, इंटल।), आदि।
    • कोड ही सत्यापित कर सकता है कि इस जादुई विधि का उपयोग करके केवल मौजूदा और अनुमत संपत्तियों को पढ़ा जा रहा है।
    • जब भी आपको एक नई समान संपत्ति बनाने की आवश्यकता होती है, तो इसे घोषित करें और उचित सरणी में अपना नाम जोड़ें और यह पूरा हो गया है। नए तरीके को परिभाषित करने की तुलना में इस तरह से तेजी है, शायद कोड के कुछ लाइनों के साथ फिर से और फिर से पूरे वर्ग कोड में दोहराया गया।

हाँ! हम ऐसा करने के लिए एक निजी विधि लिख सकते हैं, लेकिन फिर, हमारे पास कई तरीके घोषित होंगे (++ मेमोरी) जो अंत में एक और, हमेशा एक ही, विधि को बुलाते हैं। सिर्फ उन सभी पर शासन करने के लिए एक SINGLE विधि क्यों नहीं लिखी ...? [हां! पूरी तरह से इरादा! :)]

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

पठनीयता के बारे में ... खैर ... यह एक और बहस है: मैं एक आईडीई के उपयोग के लिए बाध्य होना पसंद नहीं करता (वास्तव में, मैं उनका उपयोग नहीं करता, वे मुझे बताने के लिए बाध्य करते हैं (और मुझे मजबूर करते हैं) कैसे लिखना ... और मुझे "सुंदरता" कोडिंग के बारे में मेरी पसंद है)। मैं नामकरण के बारे में सुसंगत हूं, इसलिए ctags और अन्य एड्स के एक जोड़े का उपयोग करना मेरे लिए पर्याप्त है ... वैसे भी: एक बार यह सब जादू बसने और पाने वालों के लिए होता है, मैं अन्य बसने वालों को लिखता हूं जो बहुत विशिष्ट या "विशेष" हैं। एक __set () विधि में सामान्यीकृत किया जाए। और यह उन सभी को शामिल करता है जिनकी मुझे संपत्तियों को प्राप्त करने और स्थापित करने की आवश्यकता है। बेशक: वहाँ हमेशा एक आम जमीन नहीं है, या ऐसे कुछ गुण हैं जो एक जादुई विधि कोडिंग की परेशानी के लायक नहीं है, और फिर अभी भी पुराने अच्छे पारंपरिक सेटर / गेट्टर जोड़ी है।

प्रोग्रामिंग भाषाएं बस इतनी ही हैं: मानव कृत्रिम भाषाएं। इसलिए, उनमें से प्रत्येक का अपना आत्मनिरीक्षण या उच्चारण, वाक्यविन्यास और स्वाद है, इसलिए मैं जावा या C # की तुलना में एक ही "उच्चारण" का उपयोग करके एक रूबी या पायथन कोड लिखने का नाटक नहीं करूंगा, और न ही मैं एक जावास्क्रिप्ट या PHP लिखूंगा जैसा कि पर्ल या एसक्यूएल ... उन्हें जिस तरह से उपयोग करने का मतलब है, उनका उपयोग करें।


1

सामान्यतया, पहला तरीका समग्र रूप से अधिक लोकप्रिय है क्योंकि पूर्व प्रोग्रामिंग ज्ञान वाले लोग आसानी से PHP में संक्रमण कर सकते हैं और ऑब्जेक्ट-ओरिएंटेड फैशन में काम कर सकते हैं। पहला तरीका अधिक सार्वभौमिक है। मेरी सलाह है कि कई भाषाओं में कोशिश की गई और सही है। तब, जब और यदि आप दूसरी भाषा का उपयोग करते हैं, तो आप कुछ पूरा करने के लिए तैयार होंगे ( बजाय पहिया को फिर से संवारने के समय बिताने के लिए )।


0

नेटबींस-कन्वेंशन में सोर्सकोड बनाने के कई तरीके हैं। यह अच्छा है। यह इस तरह के आसान === FALSE सोचता है। बस ट्रेडेल का उपयोग करें, विशेष रूप से यदि आप सुनिश्चित नहीं हैं कि कौन से गुणों को एनक्रिप्ट किया जाना चाहिए और कौन सा नहीं। मुझे पता है, यह एक बोई .... पीएलए ... कोड है, लेकिन डिबगिंग-कार्यों और कई अन्य लोगों के लिए यह बेहतर, स्पष्ट तरीका है। ज्यादा समय के लिए कला के प्रॉपरेंड के साथ खर्च न करें कि कैसे सरल गेटर्स और बसने के लिए। यदि आप मैजिस्टिक्स का उपयोग करते हैं तो आप कुछ डिज़ाइन पैटर्न जैसे कि लोकतंत्र-नियम इत्यादि को लागू नहीं कर सकते। विशिष्ट स्थिति में आप मैजिक_कॉल या छोटे, तेज और स्पष्ट समाधानों का उपयोग कर सकते हैं। यकीन है कि आप इस तरह से भी डिजाइन-पेटेंट के लिए समाधान बना सकते हैं, लेकिन आपको अधिक कठिन क्यों रहना चाहिए।


0

मान्यकरण + स्वरूपण / मूल्य प्राप्त करना

सेटर्स आपको डेटा को मान्य करने की अनुमति देते हैं और गेटर्स आपको डेटा को प्रारूपित या प्राप्त करने देते हैं। ऑब्जेक्ट आपको डेटा और इसके सत्यापन और स्वरूपण कोड को एक साफ पैकेज में बदलने की अनुमति देते हैं जो DRY को प्रोत्साहित करता है।

उदाहरण के लिए, निम्नलिखित सरल वर्ग पर विचार करें जिसमें जन्म तिथि शामिल है।

class BirthDate {

    private $birth_date;

    public function getBirthDate($format='Y-m-d') {
        //format $birth_date ...
        //$birth_date = ...
        return $birth_date;
    }

    public function setBirthDate($birth_date) {                   
        //if($birth_date is not valid) throw an exception ...          
        $this->birth_date = $birth_date;
    }

    public function getAge() {
        //calculate age ...
        return $age;
    }

    public function getDaysUntilBirthday() {
        //calculate days until birth days
        return $days;
    }
}

आप निर्धारित करना चाहेंगे कि मूल्य निर्धारित किया जा रहा है

  • एक वैध तिथि
  • भविष्य में नहीं

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

आप एक से अधिक formatters है कि एक ही सदस्य चर यानी पर कार्य करते हैं जोड़ सकते हैं getAge()और getDaysUntilBirthday()और आप में एक विन्यास प्रारूप लागू करने के लिए चाहते हो सकता है getBirthDate()स्थान के आधार। इसलिए मैं गेटर्स के माध्यम से लगातार पहुंच मूल्यों को पसंद करता हूं ताकि मिश्रण के $date->getAge()साथ विरोध किया जा सके $date->birth_date

जब आप वस्तुओं का विस्तार करते हैं तो गेटर्स और सेटर भी उपयोगी होते हैं। उदाहरण के लिए, मान लीजिए कि कुछ स्थानों पर 150+ वर्ष की जन्मतिथि की अनुमति देने के लिए आपके आवेदन की आवश्यकता है, लेकिन अन्य में नहीं। किसी भी कोड को दोहराए बिना समस्या को हल करने का एक तरीका यह होगा कि BirthDateवस्तु का विस्तार किया जाए और अतिरिक्त सत्यापन को सेटर में रखा जाए।

class LivingBirthDate extends BirthDate {

    public function setBirthDate($birth_date) {
        //if $birth_date is greater than 150 years throw an exception
        //else pass to parent's setter
        return parent::setBirthDate($birth_date);
    }
}

हालांकि, कई बार आपको गुणों को एक साथ सत्यापित करने की आवश्यकता होती है (और न केवल व्यक्तिगत रूप से)। मुझे लगता है कि "बसने" की अनुमति देने का मतलब है कि आप संदर्भ पर कब्जा नहीं कर रहे हैं। प्रासंगिक आधार पर सत्यापन किया जाना चाहिए। इसके अलावा, आपको अपने पास मौजूद प्रत्येक विधि पर कुछ ".Valid" झंडे को जांचने के लिए मजबूर किया जाएगा (और यदि यह गलत है तो सत्यापन करें)। कहा जा रहा है, कि बसने वाले टाइप-हिंट के लिए एक उपयोगी तरीका प्रदान करते हैं, जैसे कि जब आपके पास एक संपत्ति होती है जिसे आप वैल्यू ऑब्जेक्ट (यानी मनी) बनना चाहते हैं।
प्राग्राममेर

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

आप के साथ एक कर्मचारी वर्ग है कहो setHiredऔर setHireDate। कर्मचारी को काम पर रखने के बिना किसी को भाड़े की तारीख निर्धारित करने देना मान्य नहीं है। लेकिन इसको लागू करने का कोई तरीका नहीं है। यदि आप इसे इन बसने वालों में से किसी एक में लागू करते हैं, तो आप "सेटिंग" के आदेश के लिए मजबूर कर रहे हैं, और यह जानने के लिए डेवलपर से अधिक कोड पढ़ने की आवश्यकता है। फिर जब आप एक विधि करने जाते हैं जैसे कि $employee->promote($newPosition);आपको यह देखने के लिए कि क्या सत्यापन किया गया था या यह नहीं किया गया है और इसे फिर से करें (निरर्थक) करने के लिए एक ध्वज की जाँच करें।
प्राग्रामर

इसके बजाय, बातचीत पर कब्जा। शायद $employee->updateWorkStatus($hired, $hireDate);या अगर अधिक उन्नत $employee->adminUpdate(\Employee\AdminUpdateDTO $dto);। अब आप अपनी आवश्यकता के संदर्भ में सत्यापन कर सकते हैं और यह तय कर सकते हैं कि किसी अतिरिक्त सत्यापन की आवश्यकता है या नहीं।
प्राग्रामर 17

updateWorkStatus मूल रूप से एक सेटर फ़ंक्शन है जो 1 मान के बजाय 2 सेट करता है लेकिन अवधारणा समान है। ऐसा करने का एक तरीका है, लेकिन आप प्रासंगिक सत्यापन को एक सामान्य विधि में भी डाल सकते हैं, जो केवल तभी चलता है जब सभी संपत्तियों को एक साथ मान्य करने की आवश्यकता होती है अर्थात सत्यापन का प्रासंगिक हिस्सा दोनों से सेटहेडडेट और सेटहॉल द्वारा बुलाया जाएगा, लेकिन केवल चलेगा यदि दोनों को काम पर रखा गया है और किराए पर लिया गया है तो सही था।
18 अक्टूबर को फजीट्री

0

यह पोस्ट विशेष रूप से नहीं है __getऔर __setबल्कि __callविधि कॉलिंग को छोड़कर एक ही विचार है। एक नियम के रूप में, मैं जादू तरीकों कि टिप्पणियों और पोस्ट में उल्लिखित कारणों के लिए अधिक भार के लिए अनुमति देने से किसी भी प्रकार से दूर रहना हालांकि , मैं हाल ही में एक 3-पक्ष एपीआई में भाग रहा है जो एक सेवा है और एक उप-सेवा, उदाहरण का उपयोग करता है का उपयोग करने वाले :

http://3rdparty.api.com?service=APIService.doActionOne&apikey=12341234

इसका महत्वपूर्ण हिस्सा यह है कि इस एपीआई में सब-एक्शन के अलावा सब कुछ समान है, इस मामले में doActionOne। विचार यह है कि डेवलपर (इस वर्ग का उपयोग करने वाले अन्य लोग) उप-सेवा को नाम से बुला सकते हैं जैसे कि कुछ इस तरह विरोध किया गया है:

$myClass->doAction(array('service'=>'doActionOne','args'=>$args));

मैं इसके बजाय कर सकता था:

 $myClass->doActionOne($args);

हार्डकोड करने के लिए यह सिर्फ बहुत दोहराव होगा (यह उदाहरण बहुत ही कोड जैसा दिखता है):

public function doActionOne($array)
    {
        $this->args     =   $array;
        $name           =   __FUNCTION__;
        $this->response =   $this->executeCoreCall("APIService.{$name}");
    }

public function doActionTwo($array)
    {
        $this->args     =   $array;
        $name           =   __FUNCTION__;
        $this->response =   $this->executeCoreCall("APIService.{$name}");
    }

public function doActionThree($array)
    {
        $this->args     =   $array;
        $name           =   __FUNCTION__;
        $this->response =   $this->executeCoreCall("APIService.{$name}");
    }

protected function executeCoreCall($service)
    {
        $cURL = new \cURL();
        return $cURL->('http://3rdparty.api.com?service='.$service.'&apikey='.$this->api.'&'.http_build_query($this->args))
                    ->getResponse();
    }

लेकिन __call()मैं जादुई पद्धति से सभी सेवाओं को गतिशील तरीकों से एक्सेस करने में सक्षम हूं:

public function __call($name, $arguments)
    {
        $this->args     =   $arguments;
        $this->response =   $this->executeCoreCall("APIService.{$name}");   
        return $this;
    }

डेटा की वापसी के लिए इस गतिशील कॉलिंग का लाभ यह है कि अगर विक्रेता एक अन्य उप-सेवा को जोड़ता है, तो मुझे कक्षा में कोई अन्य विधि जोड़ने या विस्तारित वर्ग बनाने की आवश्यकता नहीं है, मुझे यकीन नहीं है कि यह उपयोगी है किसी को भी, लेकिन मुझे लगता है मैं एक उदाहरण है जहां यह दिखाएगा लगा __set, __get, __call, आदि पर विचार के लिए एक विकल्प हो सकता है क्योंकि प्राथमिक कार्य डेटा की वापसी है।


संपादित करें:

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

क्या मैं एपीआई का सही उपयोग कर रहा हूं?


-2

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


मैं आमतौर पर उस चर नाम को फ़ंक्शन नाम के रूप में उपयोग करता हूं, और उस फ़ंक्शन में वैकल्पिक पैरामीटर जोड़ता हूं ताकि जब वैकल्पिक पैरामीटर कॉलर द्वारा भरा जाए, तो उसे संपत्ति पर सेट करें और $ इस ऑब्जेक्ट (चाइनिंग) पर वापस लौटें और फिर उस वैकल्पिक पैरामीटर द्वारा निर्दिष्ट नहीं किया जाए कॉलर, मैं बस कॉलर को संपत्ति लौटाता हूं।

मेरा उदाहरण:

class Model
{
     private $propOne;
     private $propTwo;

     public function propOne($propVal = '')
     {
          if ($propVal === '') {
              return $this->propOne;
          } else {
              $this->propOne = $propVal;
              return $this;
          }
     }

     public function propTwo($propVal = '')
     {
          if ($propVal === '') {
              return $this->propTwo;
          } else {
              $this->propTwo = $propVal;
              return $this;
          }
     }
}

अब सवाल यह है कि आप खाली स्ट्रिंग के लिए प्रॉपर्टी कैसे सेट करते हैं? और आप कैसे पता लगाते हैं कि खाली स्ट्रिंग के लिए एक संपत्ति सेट करना वास्तव में विफल हो गया और एक गटर के रूप में काम किया? बस HTML फॉर्म के बारे में सोचें कि खाली फ़ील्ड्स को स्ट्रिंग्स के रूप में भेजा जाए ... और नहीं: एक अलग मान जैसे NULL का उपयोग करना डिफ़ॉल्ट समस्या का समाधान नहीं करता है।
स्वेग
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.