2010-01-27 15 views

उत्तर

33

वस्तु क्लोनिंग एक वस्तु की एक प्रति बनाने का कार्य है। Cody ने इंगित किया कि, PHP में क्लोनिंग ऑब्जेक्ट की उथली प्रति बनाकर किया जाता है। इसका मतलब है कि क्लोन ऑब्जेक्ट की आंतरिक वस्तुएं क्लोन नहीं की जाएंगी, जब तक कि आप जादू विधि __clone() को परिभाषित करके ऑब्जेक्ट को इन आंतरिक वस्तुओं को क्लोन करने के लिए स्पष्ट रूप से निर्देश न दें।

आप __clone पद्धति का उपयोग नहीं करते हैं, नई वस्तु की आंतरिक वस्तुओं मूल उद्देश्य यह है कि क्लोन किया गया था के आंतरिक वस्तुओं के रूप में स्मृति में एक ही objecs के लिए संदर्भ हो जाएगा।

इन उदाहरणों को देखें: क्लोनिंग के लिए

// in this exampe the internal member $_internalObject of both objects 
// reference the same instance of stdClass in memory. 
class CloneableClass 
{ 
    private $_internalObject; 

    public function __construct() 
    { 
     // instantiate the internal member 
     $this->_internalObject = new stdClass(); 
    } 
} 

$classA = new CloneableClass(); 
$classB = clone $classA; 


// in this exampe the internal member $_internalObject of both objects 
// DON'T reference the same instance of stdClass in memory, but are inividual instances 
class CloneableClass 
{ 
    private $_internalObject; 

    public function __construct() 
    { 
     // instantiate the internal member 
     $this->_internalObject = new stdClass(); 
    } 

    // on clone, make a deep copy of this object by cloning internal member; 
    public function __clone() 
    { 
     $this->_internalObject = clone $this->_internalObject; 
    } 
} 

$classA = new CloneableClass(); 
$classB = clone $classA; 

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

मान लें कि आपके पास एक आंतरिक ऑब्जेक्ट पता वाला क्लास उपयोगकर्ता है।

class Address 
{ 
    private $_street; 
    private $_streetIndex; 
    private $_city; 
    // etc... 

    public function __construct($street, $streetIndex, $city /* etc.. */) 
    { 
     /* assign to internal values */ 
    } 
} 

class User 
{ 
    // will hold instance of Address 
    private $_address; 

    public function __construct() 
    { 
     $this->_address = new Address('somestreet', '1', 'somecity' /* etc */); 
    } 

    public function getAddress() 
    { 
     return clone $this->_address; 
    } 
} 

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

आशा है कि यह सब कुछ समझ में आता है।

पुनश्च .:
हालांकि ध्यान रखें, कि अगर पता भी आंतरिक वस्तुओं के लिए होता है, तो आप यकीन है कि पता (के रूप में इस पोस्ट के मेरी दूसरी उदाहरण के अनुसार) द्वारा क्लोनिंग पर ही की एक गहरी प्रतिलिपि बनाता बनाने के लिए होता है पते में __clone() परिभाषित करना। अन्यथा आपको यह पता लगाने की कोशिश करने का सिरदर्द मिलेगा कि आपका डेटा खराब क्यों हुआ है।

6

ऑब्जेक्ट क्लोनिंग, PHP 5 के संदर्भ में, "shallow copy" के रूप में जाना जाता है। फिर यह क्लोन किए जाने वाले ऑब्जेक्ट पर __clone() विधि को कॉल करता है।

20

क्लोनिंग का उपयोग ऑब्जेक्ट की वास्तविक प्रति बनाने के लिए किया जाता है। अन्य चर को कोई चीज नियत एक प्रतिलिपि बनाने नहीं करता है - बल्कि, यह वस्तु के रूप में एक ही स्मृति स्थान के लिए एक संदर्भ बनाता है:

<?php 

$o= new stdclass; 
$o->a= 'b'; 
$o->b= 'c'; 

$o2= $o; 
$o2->a= 'd'; 

var_dump($o); 
var_dump($o2); 

$o3= clone $o; 
$o3->a= 'e'; 
var_dump($o); 
var_dump($o3); 

?> 

इस उदाहरण कोड होगा उत्पादन निम्नलिखित:

object(stdClass)#1 (2) { 
    ["a"]=> 
    string(1) "d" 
    ["b"]=> 
    string(1) "c" 
} 
object(stdClass)#1 (2) { 
    ["a"]=> 
    string(1) "d" 
    ["b"]=> 
    string(1) "c" 
} 
object(stdClass)#1 (2) { 
    ["a"]=> 
    string(1) "d" 
    ["b"]=> 
    string(1) "c" 
} 
object(stdClass)#2 (2) { 
    ["a"]=> 
    string(1) "e" 
    ["b"]=> 
    string(1) "c" 
} 
+1

लेकिन '$ o2 = new stdClass करने के बजाय इसे क्यों क्लोन करें;' 'o2-> a = 'd' जैसी गुणों को संशोधित करना; 'क्या वही परिणाम सही है? – samayo

+0

@ सैमायो: नहीं, यह '$ o3-> बी = $ ओ-> बी' भी करता है। ध्यान रखें कि लीपॉवर ने एक साधारण उदाहरण लिखा है, लेकिन सभी संपत्तियों की प्रतिलिपि के साथ एक ही तरह की वस्तु रखने का लाभ, जिसे मूल वस्तु को संशोधित किए बिना बाद में पुन: असाइन किया जा सकता है, अधिक जटिल परिदृश्यों में बहुत अधिक है। –

4

आप एक गहरी क्लोन की जरूरत है - जो है, बच्चे वस्तुओं और पोता वस्तुओं के क्लोन के क्लोन - आप वर्गों में से प्रत्येक में __clone अधिलेखित कर सकते हैं या तो, या बस को क्रमानुसार + ऑब्जेक्ट unserialize:

function deepClone($object) 
{ 
    return unserialize(serialize($object)); 
} 
1

जैसा कि अन्य उत्तरों में बताया गया है, clone ऑब्जेक्ट के उथले प्रति बनाता है।

आप एक गहरी प्रतिलिपि (अर्थात पुनरावर्ती कॉपी) बनाने की जरूरत है, तो आप __clone() तरीकों को ओवरलोड कर सकते हैं। MyCLabs\DeepCopy, जो और अधिक सरल और एक सरल क्लोन से शक्तिशाली है:

आप भी इस पुस्तकालय का उपयोग कर सकते हैं।

संबंधित मुद्दे