I have a class hierarchy in PHP 5.2.9.
The base class has a protected property which is an associative array.
The child classes can add some elements to the array.
The child classes are declared in the separate files (plugins), which will be created and added by multiple developers.
Which is the best way to add the elements to the property in the child classes so that declaring a new child would be as simple as possible?
<?php
class A {
protected $myproperty = array (
'A1' => 1,
'A2' => 2
);
function myprint()
{
print_r($this->myproperty);
}
};
class B extends A {
// add 'B1', 'B2' to myproperty
};
class C extends B {
// add 'C1', 'C2' to myproperty
};
$c = new C();
$c->myprint();
// The line above should print A1, A2, B1, B2, C1, C2
?>
Ideally, I'd like to make it for the developers as simple as declaring a variable or a private property, without having a need to copypaste any code.
Make use of the constructors of the inherited classes, for class B it would become something like this:
class B extends A {
function __construct() {
parent::__construct(); // Call constructor of parent class
array_push($myproperty, "B1", "B2"); // Add our properties
}
}
Same goes for class C.
If you have a lot of inherited classes, or want to provide as much support as possible, you could put this code into some function. So the other developers only need to call this function in their constructor to 'register' their child.
Related
class SubObject
{
static $static_a= 0;
public $normal_a=0;
public function __construct() {
++$this->normal_a;
++self::$static_a;
}
}
$obj1 = new SubObject();
print_r($obj1);
result is :
SubObject Object
(
[normal_a] => 1
)
My question is that why its not display output as:
SubObject Object
(
[normal_a] => 1
[static_a] => 1
)
Does static properites does not exist into the object ? Static variable or property are the way to preserver value of the variable within the context of different instance?
The static properties are attributes of the class (all instances), not an attribute of a specific instance. Here's another class ...
class Dog {
public static $species = 'mammal';
public $furColour;
public function __construct($furColour) {
$this->furColour = $furColour;
}
}
$myDog = new Dog('brown');
All dogs are mammals, in other words the entire "class" of dogs are mammals, so it makes sense to store the $species attribute at the class level (not in every instance of the class). Not all dogs have the same fur colour, that is an attribute of a specific instance of the class know as "Dog".
So, as decided by whoever designed the print_r function, it only prints attributes specific to the instance, not all the attributes of the entire class (or set of all instances). This design decision makes sense. Especially for classes that, for example, define 10's or even 100's of attributes to be used a constants: you don't want to see all these every time you print_r to debug.
FYI, if your app has a real need to get the static values, I think this works
print_r( (new ReflectionClass('SubObject'))->getStaticProperties() );
SubObject Object
(
[normal_a] => 1
[static_a] => 1
)
normal_a and static a are properties.when you dump an object it returns properties and their values.
I'm trying to work out exactly how deep inheritance goes.
For example if I start with class A
Class B extends class A
Class C extends class B
Class D extends class C
Class E extends class D
Class F extends class E
Class G extends class F
most of the lower levels are abstract classes with methods filled with code and abstract methods. its a rather large and complex structure. (doing my head in)
Will Class G still be able to access Class A methods and parameters, as well as still have access to the abstract methods from Class A ?
I'm asking because I have been having trouble with eclipse not adding the lower class methods into the auto complete. I would like to know if there is actually a limit to this or whether it's just eclipse reaching its maximum for code completion.
I'm far from a stage where I can test this with what I have done and don't want to find when I'm done that methods defined lower in the order are not accessible.
Sounds like a problem with your editor. For example, see the following quick-and-dirty demonstration:
php > class a { function foo() { echo "A::foo()\n"; } }
php > $letters = range('a', 'z');
php > for ($i = 0; $i < 25; $i++) { eval("class {$letters[$i+1]} extends {$letters[$i]} {}"); }
php > $z = new z;
php > $z->foo();
A::foo()
PHP doesn't impose any kind of restriction like this on you.
Using a canonical test like this:
<?php
abstract class A {
abstract function getValue();
}
abstract class B extends A{ }
abstract class C extends B{ }
abstract class D extends C{ }
abstract class E extends D{ }
abstract class F extends E{ }
class G extends F{
}
?>
one would expect a fatal error in that G does not in fact implement the abstract method defined in A. As you can see from the link above, this is in fact the case.
Thus, while this is a deep inheritance, it is beneath whatever limit (if any) PHP has. Rather, you're likely running into an indexer issue in the PDT.
The following php:
class A
{
public function FooA()
{
echo "A!!";
}
}
class B extends A
{
public function FooB()
{
echo "B!!";
}
}
class C extends B
{
public function FooC()
{
parent::FooB();
parent::FooA();
}
}
$test = new C();
$test->FooC();
prints:
B!!A!!
I tested this at a depth of 50 and it still functioned just fine, so you definitely can, sounds like your editor plug-in only looks so deep in the inheritance tree
This is the scenario:
There are 3 classes: class A, class B , class C
//A.php
class A {
public $something1;
public $something2;
//long list....
// i am the base class
}
//B.php
class B extends A {
// i am a child of A
}
//C.php
class C extends A{
// i do the side work
}
The program makes an object and sets values for class B like this:
$b = new B();
$b->something1 = "XYZ";
$b->something2 = "ABC";
...... long list.....
Now what I want is:
I want to call some functions of class C in class B.
I know I can do that by making an object in class B like this $c = new C();.
But I also want to pass all the variables of B i.e. (something1, something2 ....)
passed by the program to class C
I know I can do this like this:
$c->something1 = $this->something1;
$c->something2 = $this->something2 .....
But is it possible to do that without the above code because
$c->somethingN will just take too many lines and i do not like repetitive code.
I just want to know if there is any other way.
I know i can do that by making an object in class B like this $c = new C();.
If this are instance members (not static), this is the way to go.
Another way would be to use static members, like this:
class A {
public static $foo;
}
class B extends A {}
class C extends A {}
# usage:
B::$foo = 'bar';
echo C::$foo; // will output 'bar'
maybe some of you use jpgraph to generate some charts. I want to change the private attribute ($errwidth) from an jpgraph-class ( ErrorPlot ). In most cases jpgraph provides an function to set all nessesary properties. But not in this case.
Here my try:
class ErrorPlot extends Plot {
// Original class
private $errwidth=2;
...
}
class SpecialErrorPlot extends ErrorPlot {
// "Extension" to modify the attribute
function SetErrWidth( $w ){
$this->errwidth = $w;
}
}
$chart_obj = new SpecialErrorPlot( array(1,2,3,4,5,6) );
$chart_obj->SetErrWidth(10);
SpecialErrorPlot Object (
[errwidth:private] => 2
...
[errwidth] => 10
)
The result: 2 attributes! Bad enough to get these 2 attributes, but i don't understand why!?!? i hope you can help me!
Stefan
you want protected not private.
protected function and variables can be modified by child classes whereas private functions and variables cannot be modified except by that class alone.
You should look at Reflection - setAccessible()
What I would like to do is have a static factory function that you can give a series of attributes and it returns an object that is of a previously undeclared class that extends a known class.
Basically:
<?php
class foo {
public $a;
function increment($b = 1){
$this->a += $b;
}
}
function factory($name, $a){
//returns an object of class $name that extends foo with $this->a set to $a
}
so that if I write the code:
<?php
$bar = factory("bar",12);
$bar->increment(5);
print_r($bar);
if(is_a($bar, "foo")){
echo "is a Foo";
}
$moo = factory("moo", 4);
$moo->increment();
print_r($moo);
if(is_a($moo, "foo")){
echo "is a Foo";
}
I get: [edit]
bar Object
(
[a] => 17
)
is a Foo
moo Object
(
[a] => 5
)
is a Foo
But I don't know where to start looking for the commands necessary to do this. I think that in my factory function I need to somehow declare that the value of $name extends parent class but makes no changes to it, then constructs a new $name. That way it has all the functionality of the parent class, just a different type.
Check out the PHP reflection API has the methods you need to extract and build the new class there but, how to go about doing it and then creating an instance of it im not sure of. I do know its possible though because im pretty sure this is how Mocking works in PHPUnit. You might also want to look at the various Mock object related classes in PHPUnit to get some ideas as well.
That said unless you are actually adding/overloading methods, why would you even want to do this? Why not just use a property in the object or use a an interface? Whats the goal here?