EDIT: Really sorry screwed up original example. More explanation at end.
I am new to OOP finding it useful, finding it confusing.
I have looked and I think this must be a simple question but searched on things like "instantiation of subclass php" but could find nothing on point.
I want to instantiate an object and then later instantiate the subclass. Can I "add" the subclass to the existing instance?
class Dog
{
protected $owner;
protected $color;
public function setOwner($owner)
{
$this->owner = $owner;
}
public function setColor($color)
{
$this->color = $color;
}
}
class Bulldog extends Dog
{
protected $name;
protected $typeOfTail;
... set tail....
public function setName($name)
{
$this->name = $name;
}
}
class Beagle extends Dog
{
protected $name;
protected $typeOfSpots;
... set spots ....
public function setName($name)
{
$this->name = $name;
}
}
$myDog = new Dog;
$myDog -> setOwner("Bob");
$myDog1 = new Beagle;
$myDog1 -> setName("name");
obviously that will not work but if I do
$myDog = new Beagle;
$myDog -> setName("name");
I presume that just sets the owner to NULL?
Is there a way to pull the existing values (or duplicate the values) of a class into and instance of a subclass (I suppose I could do some sort of complicated method to pull all the values in but there a lot of them ....) Is this something easy to do in PHP or am I off on a LIMB?
It is 3.30 am and I apologise if this is really dumb but I have hit a wall these last couple of days and am getting behind. This seems like it could be useful in the current project.
Clarification: This is a hypothetical example. (No dogs involved with the project.) Say we have a brown dog owned by Fred and we populate an instance of dog
(pretend it is a big class with lots going on).
The next day someone says "that dog is a beagle" (ok later in the file - this is not a great example) so we want to instantiate a Beagle
class with the name Suki.
What I want is an instance of Beagle
that inherits the already existing dog
info.
Sorry once again. Off to bed.
General solution: (in case you already know the future subclass)
Just directly create an instance of the subclass. You can use it as an instance of the superclass. But some more information of what you're trying to achieve would be useful.
So it would work like this:
class Dog
{
protected $owner;
protected $color;
public function setOwner($owner)
{
$this->owner = $owner;
}
public function setColor($color)
{
$this->color = $color;
}
}
class Beagle extends Dog
{
protected $name;
public function setName($name)
{
$this->name = $name;
}
}
$myDog = new Beagle;
// here we call two methods of the Dog superclass
$myDog->setOwner("Bob");
$myDog->setColor("brown");
// now we call a method of the subclass
$myDog->setName("SomeName");
As you can see there is no need to add the methods of the parent class to the subclass again. They will be inherited implicitly and you can just use them on instances of the subclasses as if they are defined within the subclass.
If you omit one of these method calls the property will be null
, because no default value is assigned to the properties.
Specific solution: (in case you don't know the actual subclass)
If you can't create the subclass directly, create a constructor like this:
class Dog
{
protected $owner;
protected $color;
public function __construct(Dog $dog = null) {
if ($dog) {
foreach ($dog as $key => $value) {
if (property_exists($this, $key)) {
$this->{$key} = $value;
}
}
}
}
public function setOwner($owner)
{
$this->owner = $owner;
}
public function setColor($color)
{
$this->color = $color;
}
}
class Beagle extends Dog
{
protected $name;
public function setName($name)
{
$this->name = $name;
}
}
$dog = new Dog;
$dog->setOwner("Bob");
$beagle = new Beagle($dog);
$beagle->setColor("brown");
I did not test the code, so maybe there is still a bug in it, but it should get my point accross.
Parent and child classes
You can create 2 class, lets call one ParentClass
and one ChildClass
. This gives us:
class ParentClass
{
}
class ChildClass
{
}
As you can see, they are not linked in any way, shape or form, so, we need to extend the child class to use the parent, so we now have:
class ParentClass
{
}
class ChildClass extends ParentClass
{
}
Now the child speaks to the parent, so let's add a property to the parent, lets call it name
:
class ParentClass
{
protected $name; //Protected means it's private, but accessible to children
}
class ChildClass extends ParentClass
{
}
Now let's add some functionality to the child, a getter and a setter:
class ParentClass
{
protected $name;
}
class ChildClass extends ParentClass
{
public function setName($value)
{
$this->name = $value;
}
public function getName()
{
return $this->name;
}
}
As you can see, it uses the $name
from the parent, meaning it's value is available to the child, so we can do:
$childClass = new ChildClass();
$childClass->setName("My Name");
print $childClass->getName(); // prints My Name
And get a result!
Edit
Extra to show differentiation in the setters:
class Dog
{
protected $owner;
protected $color;
protected $name; // I'd put this here as all dogs have a name, right?
// Put the getters in here as all they do is return, they won't change (hopefully...)
public function getOwner()
{
return $this->owner;
}
public function getColor()
{
return $this->color;
}
public function getName()
{
return $this->name;
}
}
class Beagle extends Dog
{
public function setOwner($val)
{
$this->owner = $val;
}
public function setColor($val)
{
$this->color = $val;
}
public function setName($val)
{
$this->name = $val;
}
}
/**
* Added extra code to setters
*/
class Dalmatian extends Dog
{
public function setOwner($val)
{
$this->owner = "Owner: " . $val;
}
public function setColor($val)
{
$this->color = "Color: " . $val;
}
public function setName($val)
{
$this->name = "Name: " . $val;
}
}
As you can see in this example, there are 2 child classes, Beagle
and Dalmatian
, each with somewhat different setters for the values.
As the values are not static in the parent class, they will be different in each child, so setting one won't change the other and vica versa.
To keep values from the parent across all subclasses, use static properties as such:
class Dog
{
protected static $owner;
protected static $color; // Don't know why you'd want this kept, but okay?
}
And call using static::${variable_name};
as opposed to: $this->{variable_name};