How don't the static properties in traits lose its value when used by classes Although Traits are language assisted Copy/paste? let's consider the following example,
trait Test{
public static $var = 1;
public static function increment(){
self::$var ++;
var_dump(self::$var);
}
}
Test::increment();//2
class Test2{
use Test;
}
var_dump(Test2::$var);//2
Test2::increment();//3
This behaviour is correct in inheritance where the child extends the parent, so the child uses the parent static variables, but according to traits where copy and paste are applied, how does this work and correct?
This is an update to add another reason to the confusion I have, if the static values are reserved to specific contexts like specific class or function, so how do I able to use updated values of static properties from a different context ( the new class). I mean, if the context of trait Test is called for example Context1, and the class Test2 context is called Context2, how do I access the reserved values of the first context in another context? this is against the contexts approach we understand.
Update 3: all of this confusion depends on if the use keyword is importing the trait members in class or copy/paste?
How don't the static properties in traits lose its value when used by classes Although Traits are language assisted Copy/paste?
A trait has its own context independent of classes that use the trait, at least for static properties. If a class uses a trait with a static property, that class gets its own context, that is "its own" static property with the initial value copied from the trait:
trait T {
// '$staticProp' exists in the context of T
public static $staticProp = "in T\n";
}
// Without the need of a class that implements the trait, you can already access its value explicitly:
echo T::$staticProp; // in T
class A {
// Now 'A' gets its own '$staticProp', the initial value is copied from the context of the trait 'T'
use T;
}
// Now you can access 'A's '$staticProp' explicitly:
echo A::$staticProp; // in T
// Now we can explicitly change the value of 'A's '$staticProp'. Because 'A' has its own context, 'T::$staticProp' stays untouched:
A::$staticProp = "in A\n";
echo A::$staticProp; // in A
echo T::$staticProp; // in T
This is an update to add another reason to the confusion I have ... I mean, if the context of trait Test is called for example Context1, and the class Test2 context is called Context2, how do I access the reserved values of the first context in another context?
Like I have shown, you can always access a static property of a specific context with the class/trait name and the scope resolution operator (::
):
T::$staticProp; // Access context of trait T
A::$staticProp; // Access context of class A
all of this confusion depends on if the use keyword is importing the trait members in class or copy/paste?
I think the best way to understand the behavior is as follows:
let's consider the following example,
Here is what happens in your example:
With classes a child class includes the context of its parent:
class A {
public static $staticProp = "I am in debt\n";
}
class B extends A {}
echo A::$staticProp; // I am in debt
echo B::$staticProp; // I am in debt
A::$staticProp = "Even more debts\n";
echo A::$staticProp; // Even more debts
echo B::$staticProp; // Even more debts
B::$staticProp = "Paid debts, now debt-free\n";
echo A::$staticProp; // Paid debts, now debt-free
echo B::$staticProp; // Paid debts, now debt-free
self
normally references the class it is used in or its parent if we try to access an inherited member:
class A {
public static $aProp = 0;
}
class B extends A {
public static $bProp = 0;
public static function setProps() {
// Because B has a non inherited property '$bProp' 'self' will reference the context of class 'B':
self::$bProp = 12;
// Because B inherits a property '$aProp' 'self' will reference the inherited context of class 'A':
self::$aProp = 23;
}
public static function printProps() {
echo 'self::$bProp: ' . self::$bProp . "\n";
echo 'self::$aProp: ' . self::$aProp . "\n";
}
}
B::setProps();
B::printProps();
// self::$bProp: 12
// self::$aProp: 23
A::$aProp; // 23
B::$aProp; // 23
// Again 'A' and 'B' share the same context:
A::$aProp = 0;
echo B::$aProp; // 0
When using traits self
either references the traits context or the copied independent one of a class. Thats what happens in your example:
trait Test {
public static $var = 1;
public static function increment() {
self::$var++;
var_dump(self::$var);
}
}
// This will increment '$var' in the context of trait 'Test'
Test::increment(); // 2
// Access '$var' of trait context 'Test':
var_dump(Test::$var); // 2
class Test2 {
// Members of 'Test' are copied with current values (2) in the context of class 'Test2'
use Test;
}
// Access '$var' of class context 'Test2':
var_dump(Test2::$var); // 2
// This will increment '$var' in the context of class 'Test2'
Test2::increment(); // 3
// '$var' of trait context 'Test' has not changed:
var_dump(Test::$var); // 2
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With