Jump to content

Passing Parent Variables by Reference to Children


kael.shipman

Recommended Posts

Hey everyone,

 

Sorry in advance for this being so long, but it's really just a lot of clarification.

 

I'm having some trouble with variable referencing between related classes. I thought about using the extends keyword in my child class, but it's not so much an extension of the parent as it is a child in and of itself. The point of having the two classes is to group many distinct and unrelated instances of the child class under a blanket name and other information kept in the parent class. I do admit, however, that I'm too new to OOP to actually say with certainty that extends isn't what I need, so if you see it working, let me know!

 

At any rate, though, what I can't get to work is the sharing of variables between classes. In the example below, I only want there to be ONE memory location for $testVar and one for $errLog (within the classes, that is - the global $errLog can have its own space). I don't want any copies of those variables to exist, but indeed copies are being made and I can't figure out how to prevent that. Take a look:

 

Instantiations:

<?php
$errLog = array('test error'); //Add something to the global error Log

$a = new A; //Instantiate A
$b = $a->setB(); //Instantiate B within A
$b->chngVar('kah'); //Change the shared variable $testVar and add to the shared error Log
echo "\n".$a->testVar; //Check for the change
$a->finish(); //Merge shared local errLog with global errLog
echo "\n";
var_dump($errLog); //output global errLog
?>

 

Class Definitions:

<?php
class A { //Parent class
    var $testVar,$b,$errLog;
    function A() {
     $this->testVar = 'cha';
     $this->errLog = array();
     $this->b = array();
    }

    function setB() {
     $b = &new B($this->testVar,$this->errLog);
     $this->b[] = $b;
     echo " --- Test var should be changed: $this->testVar";
     return $b;
    }

    function finish() {
     global $errLog;
     foreach($b as $chld) {
      $chld->finish();
     }
     $errLog = array_merge($errLog,$this->errLog);
    }
}

class B { //Child class
    var $errLog,$testVar;
    function B(&$testVar,&$errLog) { //Capture REFERENCES to the parent class's passed variables
     $this->errLog = $errLog;
     $this->testVar = $testVar;

     //Output demonstrative text
     echo "Changing Test Var from '$this->testVar'";
     $this->testVar = 'nah';
     echo " to '$this->testVar'";
    }

    function chngVar($var) {
     $this->testVar = $var;
     $this->errLog[] = 'Variable Changed';
    }

    function finish() {
     //Finish up
    }
}
?>

 

The above code should display the following sequence of events:

--ESTABLISH INSTANCE OF A
   --sets $testVar to 'cha'
   --sets $errLog to new array

--ESTABLISH INSTANCE OF B
   --sets B::testVar to reference A::testVar
   --sets B::errLog to reference A::errLog
   --Output
           (B outputs) Changing Test Var from 'cha' to 'nah' (and A then outputs) --- Test var should be changed: 'nah'

--RUN B::CHNGVAR('kah')
   --sets shared testVar to 'kah'
   --adds 'Variable Changed' to shared errLog

--OUTPUT SHARED A::testVar
          kah

--RUN A::FINISH()
   --runs B::finish() (empty function) on each instance of B
   --merges A::errLog with global errLog

--OUTPUT GLOBAL ERRLOG
array(2) {
   [0]=>string(10) "test error",
   [1]=>string(16) "Variable Changed"
}

 

Instead, however, it seems to follow this sequence:

--ESTABLISH INSTANCE OF A
   --sets $testVar to 'cha'
   --sets $errLog to new array

--ESTABLISH INSTANCE OF B
   --sets B::testVar to EQUAL A::testVar
   --sets B::errLog to EQUAL A::errLog
   --Output
           (B outputs) Changing Test Var from 'cha' to 'nah' (and A then outputs) --- Test var should be changed: 'cha'

--RUN B::CHNGVAR('kah')
   --sets B::testVar to 'kah'
   --adds 'Variable Changed' to B::errLog

--OUTPUT SHARED A::testVar
          cha

--RUN A::FINISH()
   --runs B::finish() (empty function) on each instance of B
   --merges A::errLog with global errLog

--OUTPUT GLOBAL ERRLOG
array(2) {
   [0]=>string(10) "test error"
}

 

As you can see, it's simply using copies of the two variables instead of the reference that I passed. Any ideas as to how I might change that?

 

Thanks for bearing with the huge freakin' post.

 

-kael

Link to comment
Share on other sites

In PHP, the extends keyword is used to invoke inheritance.  If class B truly is a child of class A (that is, you want B to have the properties and methods of class A), then using extends is the way to go.  As far as your error is concerned, I'm not sure if this is the cause of your problem, but I believe you have a syntax error in B's constructor.  Try:

<?php

function &B(&$testVar,&$errLog) { //Capture REFERENCES to the parent class's passed variables
     $this->errLog = $errLog;
     $this->testVar = $testVar;

     //Output demonstrative text
     echo "Changing Test Var from '$this->testVar'";
     $this->testVar = 'nah';
     echo " to '$this->testVar'";
}

?>

 

The '&' before B tells the function to return a reference.  More info can be found at: http://us.php.net/manual/en/language.references.return.php

Link to comment
Share on other sites

Thanks for the reply!

 

However, I think the reference to class B is passed when I call it with the & in front of 'new', like "$b = &new B;" (http://us.php.net/manual/en/language.oop.newref.php). Besides, I don't think that's quite the problem I'm having. The class is being referenced fine, but what's being copied are the two variables that I pass to B's constructor, A::testVar and A::errLog. I've been beating my head against the wall forever on this! No fun! Any other help?

 

Oh, and the reason I didn't want B to be a true child of A is because I don't want the methods of A to pass down to B; just those two specific class variables.

 

-kael

Link to comment
Share on other sites

Alright, update:

 

It looks like it may actually just be a bug involving the internal variable referencing in general. To clarify that remarkably vague and elusive statement, what I mean is this: Instead of passing the class variable $this->testVar by reference to the constructor of B, I passed the entire object by passing simply $this. When I did that, I was able to access the variable through B::parentObject, which is the B-class variable that I assigned to the reference of the A object. When I changed $this->parentObject->testVar (where $this is called within B), it changed A::testVar as desired. (sorry to use different functions, but I had to simplify during my testing):

 

<?php
class cha {
var $testVar;
function cha() {
  $this->testVar = 'nah';
}
function newOne() {
  $ref = &new gah($this);
  return $ref;
}
}
class gah {
var $parentObject;
function gah(&$po) {
  $this->parentObject = $po;
}
function chngVar($var) {
  $this->parentObject->testVar = $var;
}
}

$cha = new cha();
$gah = $cha->newOne();
$gah->chngVar('new Value!');
echo $cha->testVar; //Outputs the EXPECTED value, "new Value!"
?>

 

So the only difference between what I did above and what I want to do in the end is that I want to pass a VARIABLE from class A by reference instead of the entire object. I suspect it may have something to do with the way the '->' works. Would using the whole scope resolution dealy work (the :: sign)? To be honest, I don't actually know what that's for, so maybe that's the answer. Help!

 

[move]A Marquee!! What an obnoxious option to include on a forum!! (No offense, forum guys; this place is great anyway)[/move]

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.