Reputation: 1914
I'm coming from Java, and wanting to use the constructor of a child class the way that it works in Java, but it appears that it doesn't work like that in PHP. The constructor of the child object can't seem to overwrite the instance variable values constructed in the parent object. Here, the parent object is being used just for the common methods between multiple child classes that will extend it. The parent class will never be called on its own.
When I instantiate a new TestPackage, I just get the initialized error values from the parent class. What gives?
<?php
interface Package{
public function getCode();
public function decode($packageCode);
public function getSetName();
public function getSetNameLang();
public function getSubsetType();
public function getSubsetTypeLang();
public function setSubsetType($typeCode);
public function getPackageOptionsArray();
public function getChoicesArray();
public function getOptionStatus($index);
public function setOptionStatus($index, $booleanStatus);
}
?>
ParentPackage.php
class ParentPackage implements Package{
private int $packageCode;
private int $subsetType;
private String $setName;
private String $setNameLang;
private $packageOptionsArray;
private $subsetTypeArray;
public function __construct(){
$this->packageCode = 0;
$this->subsetType = 0;
$this->setName = "Error: parentClass";
$this->setNameLang = "Error: Parent Class";
$this->packageOptionsArray = array("Error", //too much stuff to pass
"Error", //to a constructor as a variable
"Error",
"Error",
"Error",
"Error",
"Error",
"Error",
"Error",
"Error",
"Error",
"Error",
);
$this->subsetTypeArray = array("Error: Initializer", //16
"Error: Initializer", //32
"Error: Initializer", //48
);
//........A whole bunch more stuff that is too much to pass as a variable to a constructor
//..... OR let's just say that I don't want to do it that way
}
TestPackage.php
class TestPackage extends ParentPackage{
public function __construct(){
parent::__construct();
$this->packageCode = 0;
$this->subsetType = 0;
$this->setName = "layeredarch";
$this->setNameLang = "Layered Arch";
$this->packageOptionsArray = array("Customized welcome sign (choice of trellis half arch or smooth half arch insert up to 25 words text)",
"3 piece seating chart half arch set (print service for cards is available for a small additional fee)",
"Table numbers 1-30",
"Gold Card option04 with choice of Gifts & Cards sign",
"5 Reserved signs",
"Up to 2 Double Half Arch Small signs (Gifts & Cards, Take One, Dont Mind if I Do, In Loving Memory)",
"Up to 2 Sunset Small signs (Please Sign Our Guestbook, Gifts & Cards, In Loving Memory)",
"1 Double Half Arch Medium sign (Cheers, The Bar, Guestbook, or Custom Acrylic Text)",
"1 Double Full Arch Medium sign (Signature Drinks, or Custom Acrylic Text)",
"Unplugged Ceremony sign",
"Hairpin Record Player Prop",
"%22Mr & Mrs%22 Custom Head Table Keepsake is a free gift in addition to the items above"
);
$this->subsetTypeArray = array("Full Set", //16
"Pick Six", //32
"Pick Four" //48
);
}
Upvotes: 0
Views: 191
Reputation: 30595
private
members are local only, i.e. they cannot be read/written to via child classes. Any setter/getter in the parent class will only ever read/write from the members wrt the parent scope.
If you change the member access from private
to protected
it works.
PHP doesn't give an access error when the child class sets them because it's using the "dynamically-declared members" feature of PHP.
class ParentPackage implements Package {
protected int $packageCode;
protected int $subsetType;
protected string $setName;
protected string $setNameLang;
protected $packageOptionsArray;
protected $subsetTypeArray;
...
This is here more as an illustration of what PHP is doing rather than an actual suggestion. :-)
Another solution would be to copy the entire getter/setter methods from the parent class into the child class, effectively switching the member scope of what they access:
// Note: Don't do this. Seriously.
class ParentPackage implements Package {
private $packageOptionsArray;
public function getPackageOptionsArray() { return $this->packageOptionsArray; }
}
class TestPackage extends ParentPackage {
// Optional declaration, but without this, this property
// is dynamically created and defaults to 'public' access.
// NOTE! This variable is NOT the same as the one of the same name in the parent class.
private $packageOptionsArray;
/** Override */
public function getPackageOptionsArray() { return $this->packageOptionsArray; }
}
This technique unfortunately can lead to some very confusing code; essentially the parent class will be reading/writing its own members, and the children will have a different member. And never the twain shall meet, leading to some very interesting but very time-consuming bugs. Don't use it.
No, just mark 'em protected
and both the parent and child scopes will share the members.
Upvotes: 2