I've been running in circle for a couple hours with this problem.
Maybe it's not possible at all, or maybe there's a better OOP solution for this...
For example: I have two classes
class Base
{
public static $config;
}
class System extends Base
{
public function __construct()
{
self::$config = 2;
}
}
class Core extends Base
{
public function __construct()
{
self::$config = 3;
}
}
I always access those classes as singletons: System::HelloWorld(), Core::DoStuff();
I want the $Config attribute to be inherited from the Base class because I'm gonna need it in
almost every single class, so why define it every time over and over again.
The problem is, $Config attribute overrides itself as sonn as another class sets it's own value to it:
System::$config = 2;
Core::$config = 3;
print System::$config // it's 3 instead of 2
I do understand why that happens: Because the Base::$Config is Static - and that way - shared trough all the children. I do not want this, I want it to be static in each child, but not trough of it's children. It would be no problem, if I would actually instantiate the System and the Core classes, but I need them as Singletons...
Help me out here, maybe you know a better design pattern then this.
You don't need to use static variable at all,
<?php
Class Base{
public $Config;
}
Class System Extends Base{
Public static $obj = null;
Public static Function HelloWorld() {
if (!System::$obj) System::$obj = new System();
// call the object functions
// $obj->HelloWorld();
}
Public Function __Construct()
{
$this->Config = 2;
}
}
Class Core Extends Base{
Public Function __Construct()
{
$this->Config = 3;
}
}
?>
I came up with a relatively good solution for this. For those who may face the same problem, see here
<?php
// static change the attributes of the scope
class base
{
public static $config;
}
class a extends base
{
public function __construct()
{
self::$config = 1;
}
}
class b extends base
{
public function __construct()
{
self::$config = 2;
}
}
a::$config = 2;
b::$config = 3;
echo a::config, ',', b::$config; // 3,3
$a = new a();
echo base::$config, a::$config, b::$config, $a::$config; // 1 1 1 1
Related
I'm trying to increase the value of a variable which is declared in an abstract class, but every time I increase it from the child classes it keeps assigning 1 instead of increasing its value in every instance.
<?php
abstract class sum {
private $sumResult = 0;
}
class test1 extends sum {
private $sumResult;
public function __construct() {
$this->setSumResult();
}
public function setSumResult() {
$this->sumResult++; //here I try to increase the value of the variable
}
public function getSumResult() {
return $this->sumResult;
}
}
class test2 extends sum {
private $sumResult;
public function __construct() {
$this->setSumResult();
}
public function setSumResult() {
$this->sumResult++; //here I try to increase the value of the variable
}
public function getSumResult() {
return $this->sumResult;
}
}
$test1 = new test1();
$test2 = new test2();
echo $test2->getSumResult(); //Here it prints out 1 instead of 2.
?>
So, what I want is to increase the value of the variable sumResult in every instance, but it is not working. In the code I wrote it should return 2 instead of 1.
What am I doing wrong?
Thank you in advance
Classes provide a blueprint for the construction of instances. So, each instance has its own set of member variables. Changing a member variable in one instance doesn't change its value for another instance.
Since there's no rule without exception, there are static methods and members. These belong to the class, not the instance.
To share a variable across all instances of the classes, you will need to declare it as static and here I use protected to allow the derived classes to access the same value. Then each reference to this variable is done using self::$sumResult. You also don't need to declare the variable in each class as this can hide the field in the parent class.
abstract class sum {
protected static $sumResult = 0;
}
class test1 extends sum {
public function __construct() {
$this->setSumResult();
}
public function setSumResult() {
self::$sumResult++;
}
public function getSumResult() {
return self::$sumResult;
}
}
class test2 extends sum {
public function __construct() {
$this->setSumResult();
}
public function setSumResult() {
self::$sumResult++;
}
public function getSumResult() {
return self::$sumResult;
}
}
$test1 = new test1();
$test2 = new test2();
echo $test2->getSumResult(); //Here it prints out 2.
Just an alternative version to what others posted, if that can help. More logical this way imho, considering how static methods/properties work:
<?php
abstract class sum
{
private static $sumResult = 0;
public function __construct()
{
self::setSumResult();
}
public static function getSumResult()
{
return self::$sumResult;
}
private static function setSumResult()
{
self::$sumResult++;
}
}
class test1 extends sum {}
class test2 extends sum {}
$test1 = new test1();
$test2 = new test2();
echo sum::getSumResult();
I'm new to object-oriented PHP, and still wrapping my head around classes and subclasses.
In this simple example, $this->siteName will be empty inside the instantiated class Two (called from class One's method "build").
Is there any way for an instance of class Two to inherit that property value set by the parent?
I know I could just turn class Two into a method of class One, but I like having separate files for organization.
Is there a better way to do this?
File One
class One {
protected $siteName;
function __construct() {
$this->siteName = 'Example';
}
public function build() {
$two = new Two();
return $two->build();
}
}
File Two
class Two extends One {
public function build() {
return "<h1>$this->siteName</h1>";
}
}
By the sound of it you're trying to solve the wrong problem.
My understanding of your question is that you basically want to have the code for public function build() in another file for organisation reasons.
Here's how:
class One {
private $siteName;
public function __construct() {
$this->siteName = 'Example';
}
use One_build;
}
Assuming you have the proper autoloading setup, or have included the files correctly, you can then have your separate file:
trait One_build {
public function build() {
return "<h1>".$this->siteName."</h1>";
}
}
This allows for a horizontal spreading of your source code.
Your code does work with a few tweaks. You need to concatenate your string's h1 tags with your variable, quotes can't be around the entire thing.
Other than that, just create an instance of the class and trying it out.
class One {
protected $siteName;
function __construct() {
$this->siteName = 'Example';
}
public function build() {
$two = new Two();
return $two->build();
}
}
class Two extends One {
public function build() {
return "<h1>".$this->siteName."</h1>";
}
}
$taco = new Two();
echo $taco->build();
This will return <h1>Example</h1>
I have a parent class A and a child class B. My goal now is to initialize content (property of A). Only B knows the value that should go inside A::content.
class A
{
protected $m;
protected $n;
protected $p;
protected $content;
public function __construct() {
$this->init();
$b = new B;
$this->content = $b->getContent();
}
private function init() {
$this->m = 'Nobody';
$this->n = 'is';
$this->p = 'like';
}
public function getContent() {
return $this->content;
}
}
class B extends A
{
protected $x;
public function __construct() {
$this->init();
$this->content = $this->m.' '.$this->n.' '.$this->p.' '.$this->x.' (according to '.$this->x.')';
}
private function init() {
$this->x = 'Donald Trump';
}
}
$a = new A;
echo $a->getContent();
In my project I have some classes - let's say B,C,D (they look like B in the code above). They all have one thing in common: They need the variables and methods of A to set the value for A::content.
My question now is: Is this a "good" way to achive the goal? An alternative option could be not to use inheritance but to inject an instance of A into the constructor of B... or maybe other alternatives?
EDIT:
Okay... looks like I was not able to make myself clear. Unfortunately my english is not good enough to make my point clearer.
I'm new to OOP and I'm not trying to realize all S.O.L.I.D. principles. What I'm trying is to understand
1. where am I?
2. where do I want to get?
3. how can OOP helf me to get there?
EDIT:
in my real project I'm instantiating the parent (last two lines of my code). And the parent decides (by parsing $_GET) which child to instantiate : B, C or D
I solved the problem by changing the constructor of B... thanks to #A.P.'s hint
public function __construct() {
parent::init();
$this->init();
$this->content = $this->m.' '.$this->n.' '.$this->p.' '.$this->x.' (according to '.$this->x.')';
}
Bellow are my corrections to make what you are trying to do work. However you cannot create a A class and expect it to get the data from the B class (which is a child)
But you can access the constructor of the A class from the B class
class A
{
protected $m;
protected $n;
protected $p;
protected $content;
public function __construct() {
$this->init();
}
private function init() {
$this->m = 'Nobody';
$this->n = 'is';
$this->p = 'like';
}
public function getContent() {
return $this->content;
}
}
class B extends A
{
protected $x;
public function __construct() {
parent::__construct();
$this->init();
$this->content = $this->m.' '.$this->n.' '.$this->p.' '.$this->x.' (according to '.$this->x.')';
}
private function init() {
$this->x = 'Donald Trump';
}
public function getContent() {
return $this->content;
}
}
$B = new B;
echo $B->getContent();
so I'm trying to work out an issue I'm having in designing PHP classes. I've created a base class, and assigned private variables. I have child classes extending this base class, which make reference and changes to these private variables through functions of the base class. Here's an example, keep in mind I'm still confused about the difference between private and protected methods/variables (let me know if I'm doing it wrong!):
base.class.php
<?php
class Base {
private $test;
public function __construct(){
require('sub.class.php');
$sub = new Sub;
echo($this->getTest());
}
public function getTest(){
return $this->test;
}
protected function setTest($value){
$this->test = $value;
}
}
?>
sub.class.php
<?php
class Sub extends Base {
public function __construct(){
parent::setTest('hello!');
}
}
?>
So I'd expect the result to be hello! printed on the screen - instead there is nothing. There could be a fundamental misunderstanding of classes on my part, or maybe I'm just doing something wrong. Any guidance is very much appreciated! Thanks.
EDIT:
Thank you to everyone who contributed an answer - I think, despite the excellent solutions, that child classes are actually not what I need - it seems delegate classes may be more useful at this point, as I don't really need to reference the Base functions from within the other classes.
Should be like this:
base.class.php:
class Base {
private $test;
public function __construct() {
echo $this->getTest();
}
public function getTest() {
return $this->test;
}
protected function setTest($value) {
$this->test = $value;
}
}
sub.class.php:
class Sub extends Base {
public function __construct() {
parent::setTest('hello!'); // Or, $this->setTest('hello!');
parent::__construct();
}
}
main code:
require 'base.class.php';
require 'sub.class.php';
$sub = new Sub; // Will print: hello!
<?php
class Base {
protected static $c = 'base';
public static function getC() {
return self::$c;
}
}
class Derived extends Base {
protected static $c = 'derived';
}
echo Base::getC(); // output "base"
echo Derived::getC(); // output "base", but I need "derived" here!
?>
So what's the best workaround?
The best way to solve this is to upgrade to PHP 5.3, where late static bindings are available. If that's not an option, you'll unfortunately have to redesign your class.
Based on deceze's and Undolog's input:
Undolog is right, for PHP <= 5.2 .
But with 5.3 and late static bindings it will work , just use static instead of self inside the function - now it will work...//THX # deceze for the hint
for us copy past sample scanning stackoverflow users - this will work:
class Base {
protected static $c = 'base';
public static function getC() {
return static::$c; // !! please notice the STATIC instead of SELF !!
}
}
class Derived extends Base {
protected static $c = 'derived';
}
echo Base::getC(); // output "base"
echo Derived::getC(); // output "derived"
You have to re-implment base class method; try with:
class Derived extends Base {
protected static $c = 'derived';
public static function getC() {
return self::$c;
}
}
As you see, this solution is very useless, because force to re-write all subclassed methods.
The value of self::$c depends only on the class where the method was actually implemented, not the class from which it was called.