I want to reuse a few values from the parent class in the child class, but it seems that the child class cannot read the values that use the context $this in the parent method.
class Mother{
public function __construct($field,$val){
$this->field = $field;
$this->val = $val;
}
public function set(){
return array('val'=>$this->val,
'field'=>$this->field,
'test'=>"test");
}
}
class Sister extends Mother{
public function getVal(){
$val = parent::set();
print_r($val);
}
}
The output would be
Array ( [val] => [field] => [test] => test)
I have tried to turn the set() method static but that don't have anything to do with the problem. Can anyone tell me how to store the values in the parent class and pass it to the child class?
Your example will not print anything, because you don't call the class.
Try this
class Mother{
public function __construct($field,$val){
$this->field = $field;
$this->val = $val;
}
public function set(){
return array('val'=>$this->val,
'field'=>$this->field,
'test'=>"test");
}
}
class Sister extends Mother{
public function getVal(){
$val = parent::set();
return $val;
}
}
$class = new Sister('test1', 'test2');
print_r($class->getVal());
Related
I want to define a static property in a class, and have each child class have its own value for that property.
Here is what I tried:
class A {
static protected $v = "A";
static public function getV() {
return static::$v;
}
static public function setV($value) {
static::$v = $value;
}
}
class B extends A {}
class C extends A {}
B::setV("B");
print_r(A::getV());
print_r(B::getV());
print_r(C::getV());
print_r("\n");
C::setV("C");
print_r(A::getV());
print_r(B::getV());
print_r(C::getV());
print_r("\n");
What I expected:
ABA // C::$v hasn't been initialized, so it holds the parent's value
ABC
What I got:
BBB
CCC
So, there is only one property available, and it's the parent's one.
To get what I expected, I had to redeclare and initialize my static property in the child classes:
class B extends A {
static protected $v;
static public function init() {
self::$v = parent::$v;
}
}
B::init();
class C extends A {
static protected $v;
static public function init() {
self::$v = parent::$v;
}
}
C::init();
Result:
ABA
ABC
Is there a more elegant way to do this, without having to redeclare and initialize my property in the child classes?
You can have instead of scalar variable, an array containing all initialized values for each class. However it's not nice solution because it's pretty limited with static variables.
class A {
static protected $v = array("A" => "A");
static public function getV() {
return static::$v[get_called_class()] ?? static::$v[get_class()];
}
static public function setV($value) {
static::$v[get_called_class()] = $value;
}
}
Is it possible to extend a parent class method while overriding it ? For example:
class Foo {
public function edit() {
$item = [1,2];
return compact($item);
}
}
class Bar extends Foo {
public function edit() {
// !!! Here, is there any way I could import $item from parent class Foo?
$item2 = [3,4]; //Here, I added (extended the method with) some more variables
return compact($item, $item2); // Here I override the return of the parent method.
}
}
The issue is that I cannot edit the Foo class in any way as it is a vendor package.
I don't want to edit the vendor methods I need to extend them (add something more to their return function)
If you used array_merge() instead it will probably show the results better...
class Foo {
public function edit() {
$item = [1,2];
return $item;
}
}
class Bar extends Foo {
public function edit() {
$item = parent::edit(); // Call parent method and store returned value
$item2 = [3,4]; //Here, I added (extended the method with) some more variables
return array_merge($item, $item2); // Here I override the return of the parent method.
}
}
$a = new Bar();
print_r($a->edit());
This will output -
Array
(
[0] => 1
[1] => 2
[2] => 3
[3] => 4
)
So the call to parent::edit() will return the array from the parent class and this will be added to the array from the second class function.
Update:
I can't test this, but hopefully this will give you what your after...
class Foo {
protected function getData() {
return [1,2];
}
public function edit() {
return return view('view-file', compact($this->getData()));
}
}
class Bar extends Foo {
protected function getData() {
$item = parent::edit();
$item2 = [3,4];
return array_merge($item, $item2);
}
}
This means that the only time you create the view is in the base class, all you do is add the extra information in the derived class.
Lets say I have a class that is responsible for composing another class:
class ClassBuilder
{
protected $baseClass;
public function __construct()
{
$this->baseClass = new BaseClass();
}
public function set()
{
$this->baseClass->foo = 'bar';
}
// other methods to further modify BaseClass
}
class BaseClass
{
public $foo;
}
class ChildClass extends BaseClass {}
I want to create a method in the ClassBuilder that would allow me to update its baseClass property to an instance of ChildClass with the same property values as the current BaseClass object. How can I do that?
public function update()
{
// $this->baseClass = new ChildClass() with the current property values in BaseClass
}
I'm not sure that your overall approach is correct, but about the only way is to loop and set:
public function update()
{
$new = new ChildClass();
foreach($this->baseClass as $name => $value) {
$new->$name = $value;
}
$this->baseClass = $new;
//or
$this->baseClass = clone $new;
}
class A {
private $aa;
protected $bb = 'parent bb';
function __construct($arg) {
//do something..
}
private function parentmethod($arg2) {
//do something..
}
}
class B extends A {
function __construct($arg) {
parent::__construct($arg);
}
function childfunction() {
echo parent::$bb; //Fatal error: Undefined class constant 'bb'
}
}
$test = new B($some);
$test->childfunction();
Question:
How do I display parent variable in child?
expected result will echo 'parent bb'
echo $this->bb;
The variable is inherited and is not private, so it is a part of the current object.
Here is additional information in response to your request for more information about using parent:::
Use parent:: when you want add extra functionality to a method from the parent class. For example, imagine an Airplane class:
class Airplane {
private $pilot;
public function __construct( $pilot ) {
$this->pilot = $pilot;
}
}
Now suppose we want to create a new type of Airplane that also has a navigator. You can extend the __construct() method to add the new functionality, but still make use of the functionality offered by the parent:
class Bomber extends Airplane {
private $navigator;
public function __construct( $pilot, $navigator ) {
$this->navigator = $navigator;
parent::__construct( $pilot ); // Assigns $pilot to $this->pilot
}
}
In this way, you can follow the DRY principle of development but still provide all of the functionality you desire.
Just echo it since it's inherited
echo $this->bb;
With parent::$bb; you try to retrieve the static constant defined with the value of $bb.
Instead, do:
echo $this->bb;
Note: you don't need to call parent::_construct if B is the only class that calls it. Simply don't declare __construct in B class.
class A {
private $aa;
protected $bb = 'parent bb';
function __construct($arg) {
//do something..
}
private function parentmethod($arg2) {
//do something..
}
}
class B extends A {
function __construct($arg) {
parent::__construct($arg);
}
function childfunction() {
echo parent::$this->bb; //works by M
}
}
$test = new B($some);
$test->childfunction();`
$bb has now become the member of class B after extending class A.
So you access $bb like it's an attribute of class B.
class A {
private $aa;
protected $bb = 'parent bb';
function __construct($arg) {
//do something..
}
private function parentmethod($arg2) {
//do something..
}
}
class B extends A {
function __construct($arg) {
parent::__construct($arg);
}
function childfunction() {
echo $this->bb;
}
}
$test = new B($some);
$test->childfunction();
all the properties and methods of the parent class is inherited in the child class so theoretically you can access them in the child class but beware using the protected keyword in your class because it throws a fatal error when used in the child class.
as mentioned in php.net
The visibility of a property or method
can be defined by prefixing the
declaration with the keywords public,
protected or private. Class members
declared public can be accessed
everywhere. Members declared protected
can be accessed only within the class
itself and by inherited and parent
classes. Members declared as private
may only be accessed by the class that
defines the member.
PHP Accessing Parent Class Protected Variable & Methods
class A {
protected $bb = 'parent bb';
protected function sayHello(){
echo 'Say Hello';
}
}
class B extends A {
public function childfunction() {
echo $this->bb.'<br>';
echo $this->sayHello();
}
}
$test = new B();
$test->childfunction();
Through parent class contructor you can pass data to parent class from child class. Have a look below example for better understanding
<?php
class Student
{
public $name;
function __construct($name){
$this->name = $name;
}
}
class Test extends Student
{
public $age;
function __construct($name,$age){
$this->age = $age;
parent::__construct($name);
}
}
$obj = new Test("sajib khan" ,21);
echo $obj->name;
echo $obj->age;
?>
class A {
private $points = 100;
public function getPoints() {
return $this->points;
}
}
class B extends A {
protected $points = 70;
public function getPoints() {
return parent::getPoints();
}
}
$element = new B();
echo $element->getPoints();
change the visibility private or protected for test
Ok, so, with the code below:
class Core {
public $child;
public function start() {
$child = Loader::instance('Child');
print_r($this);
}
}
class Loader extends Core {
public static $instances;
public static function instance($class) {
if(!isset(self::$instances[$class])) {
self::$instances[$class] = new $class();
}
return self::$instances[$class];
}
}
class Child extends Core {
public function __construct() {
parent::__construct();
$this->child = 'test';
}
}
Loader::instance('Core')->start();
I should be able after a print_r($this) to see:
Core Object
(
[child] => test
)
instead of
Core Object
(
[child] =>
)
what is happening now?
Thanks again..
Within the start() method of Core class you use variable $child, that is not the property of the object. Instead write:
class Core {
public $child;
public function start() {
$this->child = Loader::instance('Child')->child;
print_r($this);
}
}
and tell me, whether this is what you wanted to accomplish.
EDIT:
I believe you can achieve what you want by referencing static variables. But be careful, how they work. Moreover, you will not see the result by invoking print_r().
Here is the code:
class Core {
static $child;
public function start() {
// invoking code that changes Core::$child inside
$child = Loader::instance('Child');
print_r($this);
}
}
and
class Child extends Core {
public function __construct() {
parent::__construct();
// changing static variable $child of both Core and Child
self::$child = 'test';
}
}
$child = Loader::instance('Child');
Shoulld be:
$this->child = Loader::instance('Child');
This is where your print_r output comes from:
$child = Loader::instance('Child');
print_r($this);
And it will print the current object ($this is a Core), rather than the newly instantiated $child (which would be a Child class).