fruffl icon

object::shallowCopy Test + dump

fruffl | 09/27/15 08:38:46 PM UTC | 0 ⭐ | 297 👁️ | Never ⏰ | []
PHP |

23.61 KB

|

None

|

0 👍

/

0 👎

    /**
     * test shallowCopy vs deepCopy
     *
     * shallowCopy:
     * \code
     * <Test>
     *  - array with closure
     *  - property with object <closure>
     *  - property with object <Alice>
     *      - array with object <closure>
     *      - property with object <closure>
     *      - property with object <Bob>
     *  - private var
     *  - public var
     *  - static object <DefaultObject>
     *  - protected var
     * \endcode
     *
     * Actions of shallowCopy:
     * - create new Test2
     * - copy values from <Test>
     * - don't touch statics
     * - property with object (not closure): copy reference, not the object
     * - property with object closure: rebind closure to <Test2>
     * - property array with objects of type closure: recursively search closures and rebind them to <Test2>
     *
     * deepCopy:
     * \code
     * <Test>
     *  - array with closure
     *  - property with object <closure>
     *  - property with object <Alice>
     *      - array with object <closure>
     *      - property with object <closure>
     *      - property with object <Bob>
     *  - private var
     *  - public var
     *  - static object <DefaultObject>
     *  - protected var
     * \endcode
     *
     * Actions of deepCopy:
     * - create new Test2
     * - copy values from <Test>
     * - don't touch statics
     * - property with object (not closure): object<IDefaultObject>->deepCopy, clone other objects
     * - property with object closure: rebind closure to <Test2>
     * - property array with objects (not closure): object<IDefaultObject>->deepCopy, clone other objects
     * - property array with objects of type closure: recursively search closures and rebind them to <Test2>
     *
     * \todo How to handle closures in traversable objects?
     */
        class test extends DefaultObject
        {
            private         $name           = 'base.name.notSet';   // name in multiple subjects are identical when closures are in old context
            public          $aV         = 'base.av.notSet'; // av: arrayValue
            public          $sV         = 'base.sv.notSet'; // sv: selfValue
            private         $private        = 0;
            static          $static         = 0;
            
            protected       $alice          = NULL;         // object as property
            
            protected       $fnA            = [];           // closure in array
            protected       $fnC            = NULL;         // closure as property
            
            function __construct($name, Alice $alice, $private, DefaultObject $static)
            {
                $this->name = $name;
                $this->alice    = $alice;
                $this->private  = $private;
                self::$static   = $static;
                
                $this->fnA['test']['self']  = function(){ return $this->aV; };
                $this->fnC          = function(){ return $this->sV; };
                
                $this->set('init'.$name);
            }
            
            function __debugInfo()
            {
                return
                [
                    'name'      => $this->name,
                    //'aV'      => $this->aV,
                    //'sV'      => $this->sV,
                    'private'   => $this->private,
                    'alice'     => $this->alice,
                    'static'    => self::$static,
                    'arrayClosure'  => $this->fnA['test']['self'],
                    'propClosure'   => $this->fnC,
                ];
            }
            
            function setClassName($n)
            {
                $this->name = $n;
            }
            
            function setAV($self, $alice)
            {
                $this->aV = 'base.av.'.$self;
                $this->alice->aV = 'alic.av.'.$alice;
            }
            
            function setSV($self, $alice)
            {
                $this->sV = 'base.sv.'.$self;
                $this->alice->sV = 'alic.sv.'.$alice;
            }
            
            function set($n)
            {
                $this->setAV('arrayClosure.'.$this->name.'.'.$n, 'arrayClosure.'.$this->name.'.'.$n);
                $this->setSV('propertyClosure.'.$this->name.'.'.$n, 'propertyClosure.'.$this->name.'.'.$n);
            }
            
            function closureInArray()
            {
                $fn = $this->fnA['test']['self'];
                echo 'closure in array:   '.$fn().PHP_EOL
                    .'                    '.$this->alice->aT();
            }
            
            function closureAsProperty()
            {
                $fn = $this->fnC;
                echo 'closure as property:'.$fn().PHP_EOL
                    .'                    '.$this->alice->sT();
            }
            
            function testClosureScope()
            {
                $this->closureInArray();
                $this->closureAsProperty();
            }
            
            function compare(test $__Test)
            {
                $r = [];
                
                $r['Test']      = $this === $__Test;
                $r['Test->fnA']     = $this->fnA === $__Test->fnA;
                $r['Test->fnC']     = $this->fnC === $__Test->fnC;
                $r['Test->alice']   = $this->alice->compare($__Test->alice);
                $r['Test::static']  = self::$static === $__Test::$static;
                
                return ["Compare {$this->name} with {$__Test->name}" => $r];
            }
        }
        
        class bob
        {
        }
        
        class alice extends DefaultObject
        {
            public          $aV         = 'alice.av.notSet';
            public          $sV         = 'alice.sv.notSet';
            protected       $fnA            = [];
            protected       $fnC            = NULL;
            protected       $__bob;
            
            function __construct()
            {
                $this->fnA['test']['alice'] = function(){ return $this->aV;};
                $this->fnC          = function(){ return $this->sV; };
                $this->__bob = new bob;
            }
            
            function __debugInfo()
            {
                return
                [
                    //'aV'      => $this->aV,
                    //'sV'      => $this->sV,
                    'arrayClosure'  => $this->fnA['test']['alice'],
                    //'propClosure' => $this->fnC,
                ];
            }
            
            function aT()
            {
                $fn = $this->fnA['test']['alice'];
                return $fn().PHP_EOL;
            }
            
            function sT()
            {
                $fn = $this->fnC;
                return $fn().PHP_EOL;
            }
            
            function compare(alice $__Test)
            {
                $r = [];
                
                $r['alice']     = $this === $__Test;
                $r['alice->fnA']    = $this->fnA === $__Test->fnA;
                $r['alice->fnC']    = $this->fnC === $__Test->fnC;
                $r['alice->__bob']  = $this->__bob === $__Test->__bob;
                
                return $r;
            }
        }
        
        $refTest = 'foooooooooooobar';
        
        
        echo '#--start closure test', PHP_EOL;
        $T = new Test('ORIG', new alice, $refTest, new DefaultObject);
        $T->set('$T.ready');
        $T->closureAsProperty();        // base name 'orig', alice name 'orig'
        echo '#----should be the same as above', PHP_EOL;
        $T->closureInArray();           // base name 'orig', alice name 'orig'
        
        echo '#--create shallow copy $D', PHP_EOL;
        $D = $T->shallowCopy();
        $T->set('$T.afterShallowCopy');
        $D->set('$D.afterShallowCopy');
        $T->closureAsProperty();        // base name 'orig', alice name 'orig'
        $D->closureAsProperty();        // base name 'orig', alice name 'orig'
        echo '#----should be the same as above', PHP_EOL;
        $T->closureInArray();           // base name 'orig', alice name 'orig'
        $D->closureInArray();           // base name 'orig', alice name 'orig'
        
        echo '#--change name of $D to "COPY"', PHP_EOL;
        $D->setClassName('COPY');
        $T->set('$T.afterNameChange$D');
        $D->set('$D.afterNameChange$D');
        echo '#----closure in ALICE returns COPY: because ORIG and COPY referencing to the same ALICE object', PHP_EOL;
        $T->closureAsProperty();        // base name 'orig', alice name 'copy'
        $D->closureAsProperty();        // base name 'copy', alice name 'copy'
        echo '#----should be the same as above', PHP_EOL;
        $T->closureInArray();           // base name 'orig', alice name 'copy'
        $D->closureInArray();           // base name 'copy', alice name 'copy'
        
        echo '#--create deep $E', PHP_EOL;
        $E = $T->deepCopy();
        $T->set('$T.afterDeepCopy');
        $D->set('$D.afterDeepCopy');
        $E->set('$E.afterDeepCopy');
        echo '#----closure in ALICE returns COPY: because ORIG and COPY referencing to the same ALICE object', PHP_EOL;
        $T->closureAsProperty();        // base name 'orig', alice name 'orig'
        $D->closureAsProperty();        // base name 'orig', alice name 'orig'
        $E->closureAsProperty();        // base name 'orig', alice name 'orig'
        $T->closureInArray();           // base name 'orig', alice name 'orig'
        $D->closureInArray();           // base name 'orig', alice name 'orig'
        $E->closureInArray();           // base name 'orig', alice name 'orig'
        
        echo '#--change name of $E to "DEEP"', PHP_EOL;
        $E->setClassName('DEEP');
        $T->set('$T.afterNameChange$E');
        $D->set('$D.afterNameChange$E');
        $E->set('$E.afterNameChange$E');
        echo '#----closure in ALICE returns COPY: because ORIG and COPY referencing to the same ALICE object', PHP_EOL;
        $T->closureAsProperty();        // base name 'orig', alice name 'orig'
        $D->closureAsProperty();        // base name 'orig', alice name 'orig'
        echo '#----both should be DEEP', PHP_EOL;
        $E->closureAsProperty();        // base name 'orig', alice name 'orig'
        echo '#----should be the same as above', PHP_EOL;
        $T->closureInArray();           // base name 'orig', alice name 'orig'
        $D->closureInArray();           // base name 'orig', alice name 'orig'
        $E->closureInArray();           // base name 'orig', alice name 'orig'
        
        var_dump($T->compare($D));
        var_dump($T->compare($E));
        
        echo '#--dump of "ORIG" ############################################################################', PHP_EOL;
        var_dump($T);
        echo '#--dump of "COPY" ############################################################################', PHP_EOL;
        var_dump($D);
        echo '#--dump of "DEEP" ############################################################################', PHP_EOL;
        var_dump($E);
        // output:
 
/*
#--start closure test
closure as property:base.sv.propertyClosure.ORIG.$T.ready
                    alic.sv.propertyClosure.ORIG.$T.ready
#----should be the same as above
closure in array:   base.av.arrayClosure.ORIG.$T.ready
                    alic.av.arrayClosure.ORIG.$T.ready
#--create shallow copy $D
closure as property:base.sv.propertyClosure.ORIG.$T.afterShallowCopy
                    alic.sv.propertyClosure.ORIG.$D.afterShallowCopy
closure as property:base.sv.propertyClosure.ORIG.$D.afterShallowCopy
                    alic.sv.propertyClosure.ORIG.$D.afterShallowCopy
#----should be the same as above
closure in array:   base.av.arrayClosure.ORIG.$T.afterShallowCopy
                    alic.av.arrayClosure.ORIG.$D.afterShallowCopy
closure in array:   base.av.arrayClosure.ORIG.$D.afterShallowCopy
                    alic.av.arrayClosure.ORIG.$D.afterShallowCopy
#--change name of $D to "COPY"
#----closure in ALICE returns COPY: because ORIG and COPY referencing to the same ALICE object
closure as property:base.sv.propertyClosure.ORIG.$T.afterNameChange$D
                    alic.sv.propertyClosure.COPY.$D.afterNameChange$D
closure as property:base.sv.propertyClosure.COPY.$D.afterNameChange$D
                    alic.sv.propertyClosure.COPY.$D.afterNameChange$D
#----should be the same as above
closure in array:   base.av.arrayClosure.ORIG.$T.afterNameChange$D
                    alic.av.arrayClosure.COPY.$D.afterNameChange$D
closure in array:   base.av.arrayClosure.COPY.$D.afterNameChange$D
                    alic.av.arrayClosure.COPY.$D.afterNameChange$D
#--create deep $E
#----closure in ALICE returns COPY: because ORIG and COPY referencing to the same ALICE object
closure as property:base.sv.propertyClosure.ORIG.$T.afterDeepCopy
                    alic.sv.propertyClosure.COPY.$D.afterDeepCopy
closure as property:base.sv.propertyClosure.COPY.$D.afterDeepCopy
                    alic.sv.propertyClosure.COPY.$D.afterDeepCopy
closure as property:base.sv.propertyClosure.ORIG.$E.afterDeepCopy
                    alic.sv.propertyClosure.ORIG.$E.afterDeepCopy
closure in array:   base.av.arrayClosure.ORIG.$T.afterDeepCopy
                    alic.av.arrayClosure.COPY.$D.afterDeepCopy
closure in array:   base.av.arrayClosure.COPY.$D.afterDeepCopy
                    alic.av.arrayClosure.COPY.$D.afterDeepCopy
closure in array:   base.av.arrayClosure.ORIG.$E.afterDeepCopy
                    alic.av.arrayClosure.ORIG.$E.afterDeepCopy
#--change name of $E to "DEEP"
#----closure in ALICE returns COPY: because ORIG and COPY referencing to the same ALICE object
closure as property:base.sv.propertyClosure.ORIG.$T.afterNameChange$E
                    alic.sv.propertyClosure.COPY.$D.afterNameChange$E
closure as property:base.sv.propertyClosure.COPY.$D.afterNameChange$E
                    alic.sv.propertyClosure.COPY.$D.afterNameChange$E
#----both should be DEEP
closure as property:base.sv.propertyClosure.DEEP.$E.afterNameChange$E
                    alic.sv.propertyClosure.DEEP.$E.afterNameChange$E
#----should be the same as above
closure in array:   base.av.arrayClosure.ORIG.$T.afterNameChange$E
                    alic.av.arrayClosure.COPY.$D.afterNameChange$E
closure in array:   base.av.arrayClosure.COPY.$D.afterNameChange$E
                    alic.av.arrayClosure.COPY.$D.afterNameChange$E
closure in array:   base.av.arrayClosure.DEEP.$E.afterNameChange$E
                    alic.av.arrayClosure.DEEP.$E.afterNameChange$E
array(1) {
  ["Compare ORIG with COPY"]=>
  array(5) {
    ["Test"]=>
    bool(false)
    ["Test->fnA"]=>
    bool(false)
    ["Test->fnC"]=>
    bool(false)
    ["Test->alice"]=>
    array(4) {
      ["alice"]=>
      bool(true)
      ["alice->fnA"]=>
      bool(true)
      ["alice->fnC"]=>
      bool(true)
      ["alice->__bob"]=>
      bool(true)
    }
    ["Test::static"]=>
    bool(true)
  }
}
array(1) {
  ["Compare ORIG with DEEP"]=>
  array(5) {
    ["Test"]=>
    bool(false)
    ["Test->fnA"]=>
    bool(false)
    ["Test->fnC"]=>
    bool(false)
    ["Test->alice"]=>
    array(4) {
      ["alice"]=>
      bool(false)
      ["alice->fnA"]=>
      bool(false)
      ["alice->fnC"]=>
      bool(false)
      ["alice->__bob"]=>
      bool(false)
    }
    ["Test::static"]=>
    bool(true)
  }
}
#--dump of "ORIG" ############################################################################
object(web\test)#2 (6) {
  ["name"]=>
  string(4) "ORIG"
  ["private"]=>
  string(16) "foooooooooooobar"
  ["alice"]=>
  object(web\alice)#3 (1) {
    ["arrayClosure"]=>
    object(Closure)#4 (1) {
      ["this"]=>
      object(web\alice)#3 (1) {
        ["arrayClosure"]=>
        *RECURSION*
      }
    }
  }
  ["static"]=>
  object(ILLI\Core\Std\DefaultObject)#7 (0) {
  }
  ["arrayClosure"]=>
  object(Closure)#8 (1) {
    ["this"]=>
    object(web\test)#2 (6) {
      ["name"]=>
      string(4) "ORIG"
      ["private"]=>
      string(16) "foooooooooooobar"
      ["alice"]=>
      object(web\alice)#3 (1) {
        ["arrayClosure"]=>
        object(Closure)#4 (1) {
          ["this"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            *RECURSION*
          }
        }
      }
      ["static"]=>
      object(ILLI\Core\Std\DefaultObject)#7 (0) {
      }
      ["arrayClosure"]=>
      *RECURSION*
      ["propClosure"]=>
      object(Closure)#9 (1) {
        ["this"]=>
        object(web\test)#2 (6) {
          ["name"]=>
          string(4) "ORIG"
          ["private"]=>
          string(16) "foooooooooooobar"
          ["alice"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            object(Closure)#4 (1) {
              ["this"]=>
              object(web\alice)#3 (1) {
                ["arrayClosure"]=>
                *RECURSION*
              }
            }
          }
          ["static"]=>
          object(ILLI\Core\Std\DefaultObject)#7 (0) {
          }
          ["arrayClosure"]=>
          *RECURSION*
          ["propClosure"]=>
          *RECURSION*
        }
      }
    }
  }
  ["propClosure"]=>
  object(Closure)#9 (1) {
    ["this"]=>
    object(web\test)#2 (6) {
      ["name"]=>
      string(4) "ORIG"
      ["private"]=>
      string(16) "foooooooooooobar"
      ["alice"]=>
      object(web\alice)#3 (1) {
        ["arrayClosure"]=>
        object(Closure)#4 (1) {
          ["this"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            *RECURSION*
          }
        }
      }
      ["static"]=>
      object(ILLI\Core\Std\DefaultObject)#7 (0) {
      }
      ["arrayClosure"]=>
      object(Closure)#8 (1) {
        ["this"]=>
        object(web\test)#2 (6) {
          ["name"]=>
          string(4) "ORIG"
          ["private"]=>
          string(16) "foooooooooooobar"
          ["alice"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            object(Closure)#4 (1) {
              ["this"]=>
              object(web\alice)#3 (1) {
                ["arrayClosure"]=>
                *RECURSION*
              }
            }
          }
          ["static"]=>
          object(ILLI\Core\Std\DefaultObject)#7 (0) {
          }
          ["arrayClosure"]=>
          *RECURSION*
          ["propClosure"]=>
          *RECURSION*
        }
      }
      ["propClosure"]=>
      *RECURSION*
    }
  }
}
#--dump of "COPY" ############################################################################
object(web\test)#12 (6) {
  ["name"]=>
  string(4) "COPY"
  ["private"]=>
  string(16) "foooooooooooobar"
  ["alice"]=>
  object(web\alice)#3 (1) {
    ["arrayClosure"]=>
    object(Closure)#4 (1) {
      ["this"]=>
      object(web\alice)#3 (1) {
        ["arrayClosure"]=>
        *RECURSION*
      }
    }
  }
  ["static"]=>
  object(ILLI\Core\Std\DefaultObject)#7 (0) {
  }
  ["arrayClosure"]=>
  object(Closure)#29 (1) {
    ["this"]=>
    object(web\test)#12 (6) {
      ["name"]=>
      string(4) "COPY"
      ["private"]=>
      string(16) "foooooooooooobar"
      ["alice"]=>
      object(web\alice)#3 (1) {
        ["arrayClosure"]=>
        object(Closure)#4 (1) {
          ["this"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            *RECURSION*
          }
        }
      }
      ["static"]=>
      object(ILLI\Core\Std\DefaultObject)#7 (0) {
      }
      ["arrayClosure"]=>
      *RECURSION*
      ["propClosure"]=>
      object(Closure)#30 (1) {
        ["this"]=>
        object(web\test)#12 (6) {
          ["name"]=>
          string(4) "COPY"
          ["private"]=>
          string(16) "foooooooooooobar"
          ["alice"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            object(Closure)#4 (1) {
              ["this"]=>
              object(web\alice)#3 (1) {
                ["arrayClosure"]=>
                *RECURSION*
              }
            }
          }
          ["static"]=>
          object(ILLI\Core\Std\DefaultObject)#7 (0) {
          }
          ["arrayClosure"]=>
          *RECURSION*
          ["propClosure"]=>
          *RECURSION*
        }
      }
    }
  }
  ["propClosure"]=>
  object(Closure)#30 (1) {
    ["this"]=>
    object(web\test)#12 (6) {
      ["name"]=>
      string(4) "COPY"
      ["private"]=>
      string(16) "foooooooooooobar"
      ["alice"]=>
      object(web\alice)#3 (1) {
        ["arrayClosure"]=>
        object(Closure)#4 (1) {
          ["this"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            *RECURSION*
          }
        }
      }
      ["static"]=>
      object(ILLI\Core\Std\DefaultObject)#7 (0) {
      }
      ["arrayClosure"]=>
      object(Closure)#29 (1) {
        ["this"]=>
        object(web\test)#12 (6) {
          ["name"]=>
          string(4) "COPY"
          ["private"]=>
          string(16) "foooooooooooobar"
          ["alice"]=>
          object(web\alice)#3 (1) {
            ["arrayClosure"]=>
            object(Closure)#4 (1) {
              ["this"]=>
              object(web\alice)#3 (1) {
                ["arrayClosure"]=>
                *RECURSION*
              }
            }
          }
          ["static"]=>
          object(ILLI\Core\Std\DefaultObject)#7 (0) {
          }
          ["arrayClosure"]=>
          *RECURSION*
          ["propClosure"]=>
          *RECURSION*
        }
      }
      ["propClosure"]=>
      *RECURSION*
    }
  }
}
#--dump of "DEEP" ############################################################################
object(web\test)#26 (6) {
  ["name"]=>
  string(4) "DEEP"
  ["private"]=>
  string(16) "foooooooooooobar"
  ["alice"]=>
  object(web\alice)#34 (1) {
    ["arrayClosure"]=>
    object(Closure)#45 (1) {
      ["this"]=>
      object(web\alice)#34 (1) {
        ["arrayClosure"]=>
        *RECURSION*
      }
    }
  }
  ["static"]=>
  object(ILLI\Core\Std\DefaultObject)#7 (0) {
  }
  ["arrayClosure"]=>
  object(Closure)#44 (1) {
    ["this"]=>
    object(web\test)#26 (6) {
      ["name"]=>
      string(4) "DEEP"
      ["private"]=>
      string(16) "foooooooooooobar"
      ["alice"]=>
      object(web\alice)#34 (1) {
        ["arrayClosure"]=>
        object(Closure)#45 (1) {
          ["this"]=>
          object(web\alice)#34 (1) {
            ["arrayClosure"]=>
            *RECURSION*
          }
        }
      }
      ["static"]=>
      object(ILLI\Core\Std\DefaultObject)#7 (0) {
      }
      ["arrayClosure"]=>
      *RECURSION*
      ["propClosure"]=>
      object(Closure)#43 (1) {
        ["this"]=>
        object(web\test)#26 (6) {
          ["name"]=>
          string(4) "DEEP"
          ["private"]=>
          string(16) "foooooooooooobar"
          ["alice"]=>
          object(web\alice)#34 (1) {
            ["arrayClosure"]=>
            object(Closure)#45 (1) {
              ["this"]=>
              object(web\alice)#34 (1) {
                ["arrayClosure"]=>
                *RECURSION*
              }
            }
          }
          ["static"]=>
          object(ILLI\Core\Std\DefaultObject)#7 (0) {
          }
          ["arrayClosure"]=>
          *RECURSION*
          ["propClosure"]=>
          *RECURSION*
        }
      }
    }
  }
  ["propClosure"]=>
  object(Closure)#43 (1) {
    ["this"]=>
    object(web\test)#26 (6) {
      ["name"]=>
      string(4) "DEEP"
      ["private"]=>
      string(16) "foooooooooooobar"
      ["alice"]=>
      object(web\alice)#34 (1) {
        ["arrayClosure"]=>
        object(Closure)#45 (1) {
          ["this"]=>
          object(web\alice)#34 (1) {
            ["arrayClosure"]=>
            *RECURSION*
          }
        }
      }
      ["static"]=>
      object(ILLI\Core\Std\DefaultObject)#7 (0) {
      }
      ["arrayClosure"]=>
      object(Closure)#44 (1) {
        ["this"]=>
        object(web\test)#26 (6) {
          ["name"]=>
          string(4) "DEEP"
          ["private"]=>
          string(16) "foooooooooooobar"
          ["alice"]=>
          object(web\alice)#34 (1) {
            ["arrayClosure"]=>
            object(Closure)#45 (1) {
              ["this"]=>
              object(web\alice)#34 (1) {
                ["arrayClosure"]=>
                *RECURSION*
              }
            }
          }
          ["static"]=>
          object(ILLI\Core\Std\DefaultObject)#7 (0) {
          }
          ["arrayClosure"]=>
          *RECURSION*
          ["propClosure"]=>
          *RECURSION*
        }
      }
      ["propClosure"]=>
      *RECURSION*
    }
  }
}

Comments