How to make an abstract variable static to a sub class - php

<?php
abstract class A {
public static $var = "A";
public function setVar() {
}
public function test() {
$this->setVar();
echo static::$var;
}
public function returnVar() {
return static::$var;
}
}
class B extends A {
public function setVar() {
static::$var = 'B';
}
}
class C extends A {
public function setVar() {
static::$var = 'C';
}
}
$class = new B();
$class->test();
$class2 = new C();
$class2->test();
echo "</br>";
echo $class->returnVar();
echo $class2->returnVar();
?>
What I'm trying to do is make the variable $var static to the class that extends abstract class A without having to re-declare it else where.
So say perhaps I create multiple objects from class B that extends A, I want all objects made from class B to share the same $var value.
Say I then create objects based on class C, they should all share the same value of $var...
This is the result I'm currently getting:
BC
CC
However, what I'm looking for is:
BC
BC
Thanks

Try it like that:
#setting
public function setVar() {
static::$var[get_class($this)] = 'B';
}
#getting in abstract
public function returnVar() {
return static::$var[get_class($this)];
}
#add this in the abstract class
public function setVar();

Related

Access Static var from multiplie class inheritance (PHP)

How can I access $var from C class, i try with parent::parent::$var but this didn't work.
<?php
class A {
protected static $var = null;
public function __construct(){
self::$var = "Hello";
}
}
class B extends A {
parent::__construct();
//without using an intermediate var. e.g: $this->var1 = parent::$var;
}
class C extends B {
//need to access $var from here.
}
?>
Since the variable is static you can access the variable like below -
A::$var;
As long as the property isn't declared as private, then you can just use self::. Anything other than private properties are available from anywhere in the hierarchy.
class A {
protected static $var = null;
public function __construct(){
self::$var = "Hello";
}
}
class B extends A {
}
class C extends B {
function get() { echo self::$var; }
}
(new C)->get();
Hello
See https://eval.in/1022037

Multiple inheritance + Multi-Level inheritance in PHP: Is there a pattern or possibility to solve constructor inheritance?

Have a look at the following example:
class A {
protected $a;
public function __construct() {
$this->a = "foo";
}
}
trait Q {
protected $q;
public function __construct() {
$this->q = "happy";
}
}
class B extends A {
use Q;
protected $b;
public function __construct() {
$this->b = "bar";
}
}
trait X {
protected $x;
public function __construct() {
$this->x = "lorem";
}
}
class C extends B {
use X;
protected $c;
public function __construct() {
$this->c = "sure";
}
public function giveMeEverything() {
echo $this->a." ".$this->b." ".$this->c." ".$this->x." ".$this->q;
}
}
$c = new C();
$c->giveMeEverything();
This works just fine - the output is:
sure
The thing is that I want all classes and and traits within the tree to initialize their member variables. Desired output:
foobarsureloremhappy
It must not be solved with constructors! I just want the member variables to be populated on initialization, but I still had no good idea how to solve this. In a real world example this is more complex, therefore please do not $a = "foo"; just within the variables declaration.
The problem is that traits cannot be instantiated so __construct() is kind of meaningless.
The best approach is to initialize your member variables using the class constructor; that's why constructors exist.
If you want to initialize some members that are declared in a trait, then have a trait function and call it in the appropriate class constructor, example:
trait Q {
protected $a;
public function initQ() { $this->a = "whatever"; }
}
class MyClass {
use Q;
public function __construct() {
$this->initQ();
}
}

How access outside variables from within class?

I have two class called them class A and B. I created the 'A' class. And in this i create a 'B' class. How can i access the 'A' class variable from 'B' class?
class A
{
var letter;
var writers;
function __construct()
{
$this-letter = 'SOMETHING';
$this->writers = new B;
}
}
class B extends Writers
{
function __construct()
{
parent::__construct();
echo $letter; //This is where i want to acces outside variable (CLASS 'A')
}
}
I hope i was clear. I'm just rookie on OOP-ing. Please help me.
You can't, because $letter in A is was not declared public and B doesn't extend A.
If you don't want to expose A's data (one of the important OOP principles), you should use encapsulation. Create a getter in the A class
public function getLetter()
{
return $this->letter;
}
And then in B's construct method, create an instance of A and use said getter
$a = new A();
$letter = $a->getLetter();
In case you really need to use this structure, I guess you could do something like this:
class A
{
var letter;
var writers;
function __construct()
{
$this-letter = 'SOMETHING';
$this->writers = new B($this);
}
}
class B extends Writers
{
var $a;
function __construct(A $a)
{
parent::__construct();
$this->a = $a;
echo $this->a->letter;
}
}
This way, B would hold a reference to the A object it was created by. However, I rather recommend you to change your class topology, if possible.
Your B class needs to somehow have a reference to an A object. You could simply add to B :
class B extends Writers
{
private $a;
function __construct()
{
parent::__construct();
echo $letter; //This is where i want to acces outside variable (CLASS 'A')
}
public function A($a)
{
$this->a = $a;
}
}
Next, simply have your A object give a reference to itself to its B object.
class A
{
var letter;
var writers;
function __construct()
{
$this-letter = 'SOMETHING';
$this->writers = new B;
$this->writers->A($this);
}
}
The alternative would be static method.
It's hard to tell exactly what you want, but as I interpreted it:
class A extends Writers
{
var letter;
var writers;
function __construct()
{
$this-letter = 'SOMETHING';
$this->writers = new B;
}
}
class B extends A
{
function __construct()
{
parent::__construct();
echo $this->letter; //This is where i want to acces outside variable (CLASS 'A')
}
}
You can use static variable. like this:
class A
{
static $letter;
function __construct()
{
self::$letter = 'SOMETHING';
}
}
$objA = new A();
class B
{
function __construct()
{
$letter = A::$letter;
echo $letter; //print SOMETHING
}
}

Access private properties in a class hierarchy from a common base function

I want to define a method once in a base class and call it in successive constructors in a class hierarchy. Each time is it called I want it to operate on the properties of the class from which it is called.
For example, A is the base class and the method is defined here. B inherits from A, and C inherits from B.
When I instantiate the concrete class C the constructor will call the base class method, and I want it to operate on the properties of C. (This will be a private array which I will populate when I initialise it).
The constructor of C then calls parent::__construct. When the B constructor calls the base class method, the method should operate on the properties of B. Before the B constructor is complete it will call parent::_construct, and the A constructor will operate on the properties of A.
I was looking into LSB, but it won't work correctly because parent::__construct is a forwarding call. I tried using the result of get_parent_class() in place of parent::, but my calls to static::propertyName error out because propertyName is not a constant.
How can I do this?
EDIT: Here's a code example. The code below outputs "P Q P Q P Q". I want it to output "P Q R S T U".
class A {
private $property = array('P','Q');
function __construct() {
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class B extends A {
private $property = array('R','S');
function __construct()
{
parent::__construct();
$this->myMethod();
}
}
class C extends B {
private $property = array('T','U');
function __construct()
{
parent::__construct();
$this->myMethod();
}
}
$c = new C();
As far as I know it is not possible. In case of private the variable is not available to method and in case of public/protected its overwritten.
You can get your desired result by passing
$this->property
in each myMethod call like this -
$this->myMethod($this->property)
and changing your myMethod definition accordingly.
If I got you right, this is your example:
class A {
public function __construct() {
}
public function someMethod($arg) {
$someProperty = $arg;
}
}
class B extends A {
public function __construct() {
parent::__construct();
}
}
class C extends B {
private $someProperty;
public function __construct() {
parent::__construct();
}
}
Everything works as you would expect. There is only one problem; class A has no property someProperty. If you want to use it in class A, you have to define it there. If you want to use it in subclasses, you have to make it protected. Your class A has therefore to look like this:
class A {
protected $someProperty;
public function __construct() {
}
public function someMethod($arg) {
$this->someProperty = $arg;
}
}
Now you can use it in class B and C, and class A can use the property with someMethod:
$instance = new C();
$instance->someMethod("test");
Because your example has $property defined as private and you never override myMethod, when an object of type C or B is instantiated, it runs class A's constructor, which calls myMethod() from class A where the value of $property is array('P', 'Q');.
If you want it to print 'P Q R S T U' you'll have to override myMethod() and call it from each individual class' __construct() method, OR declare $property to be protected so that the child classes can overwrite its value.
Something like this:
class A {
private $property = array('P','Q');
function __construct() {
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class B extends A {
private $property = array('R','S');
function __construct()
{
parent::__construct();
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class C extends B {
private $property = array('T','U');
function __construct()
{
parent::__construct();
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
$c = new C();
OR THIS:
class A {
protected $property = array('P','Q');
function __construct() {
$this->myMethod();
}
public function myMethod() {
foreach ($this->property as $value) {
echo $value . " ";
}
}
}
class B extends A {
protected $property = array('R','S');
function __construct()
{
parent::__construct();
$this->myMethod();
}
}
class C extends B {
protected $property = array('T','U');
function __construct()
{
parent::__construct();
$this->myMethod();
}
}
$c = new C();
proptery cannot be overloaded in child classes. Once you have a C, it does not have the private properties of A anymore. It has no way to access them (outside of reflection). The only way you would be able to do this would be to pass the properties to someMethod in a chain, but this requires access to the desired property.
Using protected would not work either because then the children would just override the parent property.
The solution to this is not have have C be an a (is-a) but have C have the properties of an A (has-a .. composition). This would require some rework of your hierarchy, though, and your calls would have to be more explicit. Something like
class C {
private $b;
private $properties = array('T', 'U');
public function __construct(B $b) {
$this->b = $b;
}
public function someMethod() {
$this->b->someMethod($properties);
}
}
class B {
private $properties = array('R', 'S');
private $a;
public function __construct(A $a) {
$this->a = $a;
}
public function someMethod($properties) {
$this->a->someMethod(array_merge($this->properties, $properties));
}
}
class A {
private $properties = array('P', 'Q');
public function someMethod($properties) {
//your implementation plus an array_merge
}
}
This obviously increases verbosity in your definitions, which is bad. You may want to reconsider why you have to do some things the way you are doing them. You may be able to get around this with traits (assuming you have PHP 5.4)

Calling extended class function from parent class

I'm new to OO PHP. Got some questions.
class a {
protected function a1() {
...
}
}
class b extends a {
public function b1() {
...
}
}
Let's say we have 2 classes like explained above. I'm calling b's method like example below
class a {
var $b;
function __construct()
{
$b = new b();
}
protected function a1() {
$b->b1();
}
}
class b extends a {
public function b1() {
...
}
}
I know that, it's possible to call parent class'es method from extended class, but I wonder if reverse way is possible? I mean, calling extended classes method from inside parent class (in this case, class b's method from class a) without declaring in __contruct, simply by $this->b();?
Yes, you can call a method in the extending class.
<?php
class a
{
public function a1 ()
{
$this->b1();
}
protected function b1()
{
echo 'This is in the a class<br />';
}
}
class b extends a
{
protected function b1()
{
echo 'This is in the b class<br />';
}
}
class c extends a
{
protected function b1()
{
echo 'This is in the c class<br />';
}
}
$a = new a();
$a->a1();
$b = new b();
$b->a1();
$c = new c();
$c->a1();
?>
This will result in:
This is in the a class
This is in the b class
This is in the c class
You may also be interested in abstract classes http://us3.php.net/manual/en/language.oop5.abstract.php
use Magic methods of PHP __call or __callStatic
Reference

Categories