2010-05-21 11 views
14

से विधि के रूप में बंद करने को परिभाषित करता है मैं php5.3 और बंद करने के साथ खेलने की कोशिश कर रहा हूं।कक्षा

मैं यहां देखता हूं (लिस्टिंग 7. किसी ऑब्जेक्ट के अंदर बंद करें: http://www.ibm.com/developerworks/opensource/library/os-php-5.3new2/index.html) कि कॉलबैक फ़ंक्शन में $ $ का उपयोग करना संभव है, लेकिन ऐसा नहीं है। इसलिए मैं के रूप में उपयोग चर इस $ देने की कोशिश:

$self = $this; 
$foo = function() use($self) { //do something with $self } 

तो इसी उदाहरण के लिए:

class Dog 
{ 
private $_name; 
protected $_color; 

public function __construct($name, $color) 
{ 
    $this->_name = $name; 
    $this->_color = $color; 
} 
public function greet($greeting) 
{ 
    $self = $this; 
    return function() use ($greeting, $self) { 
     echo "$greeting, I am a {$self->_color} dog named {$self->_name}."; 
    }; 
} 
} 

$dog = new Dog("Rover","red"); 
$dog->greet("Hello"); 

Output: 
Hello, I am a red dog named Rover. 

यह सब उदाहरण के पहले स्ट्रिंग मुद्रित नहीं करता, लेकिन समारोह लौटने के लिए, लेकिन वह नहीं है मेरी समस्या।

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

function greet($greeting, $object) { 
    echo "$greeting, I am a {$self->_color} dog named {$self->_name}."; 
} 

और मैं चाहता हूँ:

public function greet($greeting) { 
    echo "$greeting, I am a {$self->_color} dog named {$self->_name}."; 
} 

कौन सा कुत्ता से है और वैश्विक नहीं।

+0

नहीं, मैं समझ में नहीं आया कि आप क्या चाहते। यदि बधाई एक विधि है, दृश्यता जनता के लिए defauls, तो आपके दो अंतिम कोड ब्लॉक बराबर हैं। – Artefacto

+0

PHP 5.3 जारी होने से पहले क्लोजर में '$ this' का जादू इंजेक्शन गिरा दिया गया है। दरअसल, इसे PHP के आने वाले संस्करण के लिए स्थगित कर दिया गया था। कुछ क्लोजर :: बाइंडो 'जैसी कुछ चीजें होंगी जो कि वस्तुओं को बाम्बाडा के संदर्भ के रूप में बाध्य करने के लिए उपयोग कर सकती हैं। –

उत्तर

2

वैसे यह समझ में आता है कि आप किसी ऑब्जेक्ट के निजी और संरक्षित फ़ील्ड तक नहीं पहुंच सकते हैं। और स्पष्ट रूप से $self को आपके फ़ंक्शन में पास करके, इसे सामान्य वस्तु के रूप में माना जाता है। encapsulation की बात के लिए

class Dog 
{ 
    private $_name; 
    protected $_color; 

    public function __construct($name, $color) 
    { 
     $this->_name = $name; 
     $this->_color = $color; 
    } 
    public function getName() { 
     return $this->_name; 
    } 
    public function getColor() { 
     return $this->_color; 
    } 
    public function greet($greeting) 
    { 
     $self = $this; 
     return function() use ($greeting, $self) { 
      echo "$greeting, I am a {$self->getColor()} dog named {$self->getName()}."; 
     }; 
    } 
} 

आप गेटर (और setters) बनाना चाहिए वैसे भी,:
आप अर्थात इन मूल्यों को एक्सेस करने के लिए ही टिककर खेल बनाना चाहिए।


एक और नोट: जिस लेख से आप लिंक करते हैं वह PHP 5.3 के अंतिम संस्करण से पहले प्रकाशित हुआ था। शायद इस अंतर्निहित वस्तु को हटा दिया गया था।

+0

हाँ मुझे पता है कि यह वर्तमान संस्करण की तरह नहीं है। मैं चाहता हूं कि कक्षा कुत्ते का एक नया कार्य तैयार करना है और फिर फ़ंक्शन में मैं $ $ को पास किए बिना $ तक पहुंच सकता हूं। – Charles

8

ठीक है, इसका पूरा कारण यह है कि आप इसका उपयोग नहीं कर सकते हैं, क्योंकि बंद पृष्ठभूमि (क्लोजर क्लास) में एक वस्तु है।

इसके आसपास दो तरीके हैं। सबसे पहले, .. __invoke विधि जोड़ने (यदि आप $ obj() फोन क्या कहा जाता है) है

class Dog { 

    public function __invoke($method) { 
     $args = func_get_args(); 
     array_shift($args); //get rid of the method name 
     if (is_callable(array($this, $method))) { 
      return call_user_func_array(array($this, $method), $args); 
     } else { 
      throw new BadMethodCallException('Unknown method: '.$method); 
     } 
    } 

    public function greet($greeting) { 
     $self = $this; 
     return function() use ($greeting, $self) { 
      $self('do_greet', $greeting); 
     }; 
    } 

    protected function do_greet($greeting) { 
     echo "$greeting, I am a {$this->_color} dog named {$this->_name}."; 
    } 
} 

आप बंद करना चाहते हैं यदि आप मेजबान वस्तु को संशोधित परिवर्तन नहीं करने के लिए, आप बस वापसी समारोह को बदल सकते हैं की तरह कुछ:

public function greet($greeting) { 
    $self = (clone) $this; 
    return function() use ($greeting, $self) { 
     $self('do_greet', $greeting); 
    }; 
} 

अन्य विकल्प, एक सामान्य गेटर प्रदान करना है:

class Dog { 

    public function __get($name) { 
     return isset($this->$name) ? $this->$name : null; 
    } 

} 

अधिक जानकारी के लिए देखें: http://www.php.net/manual/en/language.oop5.magic.php

+0

मैं जोड़ता हूं कि आप प्रतिबिंब के माध्यम से क्षेत्र को सुलभ बना सकते हैं। – Artefacto

+1

आप PHP 5.4 – dave1010

+0

के रूप में बंद होने में '$ this' का उपयोग कर सकते हैं यह एक पुराना उत्तर है जो मुझे पता है। लेकिन यह ध्यान देने योग्य है कि क्लोजर :: बाइंड() (http://www.php.net/manual/en/closure.bind.php) यहां एक व्यवहार्य समाधान भी है। –

4

PHP 5.4 के रूप में।0 Alpha1, आप एक वस्तु उदाहरण के संदर्भ में से $this पहुँच सकते हैं:

<?php 
class Dog 
{ 
    private $_name; 
    protected $_color; 

    public function __construct($name, $color) 
    { 
    $this->_name = $name; 
    $this->_color = $color; 
    } 

    public function greet($greeting) 
    { 
    $func = function() use ($greeting) { 
     echo "$greeting, I am a {$this->_color} dog named {$this->_name}."; 
    }; 

    $func(); 
    } 
} 

$dog = new Dog("Rover","red"); 
$dog->greet("Hello"); 

तुम भी ऐसा कर सकते हैं:

$dog = new Dog("Rover", "red"); 
$getname = Closure::bind($dog, function() { return $this->_name; }); 
echo $getname(); // Rover 

आप देख सकते हैं, यह आसानी से निजी डेटा के साथ गड़बड़ करने के लिए संभव है। .. तो सावधान रहें।

0

मैं कक्षा में कॉलबैक अलग करने के अपने काम में इस create_closure() का उपयोग करें:

<?php 
function create_closure($fun, $args, $uses) 
     {$params=explode(',', trim($args.','.$uses, ',')); 
      $str_params=''; 
      foreach ($params as $v) 
        {$v=trim($v, ' &$'); 
        $str_params.='\''.$v.'\'=>&$'.$v.', '; 
        } 
      return "return function({$args}) use ({$uses}) {{$fun}(array({$str_params}));};"; 
     } 
?> 

उदाहरण:

<?php 
$loop->addPeriodicTimer(1, eval(create_closure('pop_message', '$timer', '$cache_key, $n, &$response, &$redis_client'))); 

function pop_message($params) 
     {extract($params, EXTR_REFS); 
      $redis_client->ZRANGE($cache_key, 0, $n) 
          ->then(//normal 
            function($data) use ($cache_key, $n, &$timer, &$response, &$redis_client) 
            {//... 
            }, 
            //exception 
            function ($e) use (&$timer, &$response, &$redis_client) 
            {//... 
            } 
           ); 
     } 
?>