In php, if A extends B, does B's _constrctor() get executed automatically when A is instantiated? or do I have to call parent->_constructor()?
PHP looks for the top-most (closest to the instantiated class) __construct method it can find. It then executes that one only.
Class A {
public function __construct() {
echo "From A";
}
}
Class B extends A {
public function __construct() {
echo "From B";
}
}
Class C extends A {}
Class D extends B {}
Class E extends B {
public function __construct() {
echo "from E";
}
}
new A(); // From A
new B(); // From B
new C(); // From A
new D(); // From B
new E(); // From E
And parent accesses the next one up the list until there are no more (at which point it'll generate an error)...
So, in class E, running parent::__construct() would execute class B's constructor.
In class B, running parent::__construct() would execute class A's constructor.
In class A, running parent::__construct() will generate an error since there is no constructor...
The answer is you have to call it.
A simple test:
class A {
public function __construct() {
echo 'A';
}
}
class B extends A {
public function __construct() {
echo 'B';
}
}
$ab = new B();
Should tell you all you need to know.
You need to call "parent::__construct()" from A's constructor, if A has one. Otherwise you don't need to.
class A {
function __construct() {
echo 5;
}
}
class B_no_Constructor extends A {
}
class B_with_Constructor extends A {
function __construct(){}
}
//try one
//new B_no_Constructor; //outputs 5
//new B_with_Constructor; //outputs nothing
Related
Please check the example can I use the A function in C like the below example? If not then how can I use the A function in C?
class A {
public function a()
{
return 'hello';
}
}
class B extends A {
//
}
class C extends B {
// Can I use the A function in C?
}
Methods are inherited through any number of nested classes.
class A {
public function a()
{
return 'hello';
}
}
class B extends A {
//
}
class C extends B {
function c() {
echo $this->a();
}
}
$x = new C();
$x->c(); // This will print `Hello`.
echo $x->a(); // So will this.
Is something like the following possible in PHP?
$blah = 'foo1';
class foo2 extends $blah {
//...
}
class foo1 {
//...
}
This gives an error.
I want to dynamically set $blah so I can extend whatever class I want.
Edit: The reason for wanting to do this because I wanted to use a function out of another class in a related class. In the end it would have been something like:
Final extends foo1 extends foo2 extends foo3 extends foo4 extends parent { ... }
In the end I decided to instantiate the other class within the class and use it. Not the best options because they both you 2 of the same classes, but this won't be used that often, so it will work for now.
You're assuming here php executes top to bottom, but it doesn't quite work like that:
<?php
foo(); # works
function foo(){
print "bar";
}
<?php
foo(); #dies
if( $i == 1 )
{
function foo(){
print "bar";
}
}
<?php
$i = 1;
if( $i == 1 )
{
function foo(){
print "bar";
}
}
foo(); #works
Now, although you can conditionally create classes:
<?php
class A { }
class B { }
if( false ){
class C extends B {
public static function bar(){
print "baz";
}
}
}
C::bar(); # dies
You cant instantiate one at runtime from a variable:
<?php
class A { }
class B { }
$x = 'B';
if( false ){
class C extends $x {
public static function bar(){
print "baz";
}
}
}
C::bar();
---> Parse error: syntax error, unexpected T_VARIABLE, expecting T_STRING in /tmp/eg.php on line 7
There is a way to do it with Eval, but you really don't want to go there:
<?php
class A { }
class B { }
$x = 'B';
if( true ){
$code =<<<EOF
class C extends $x {
public static function bar(){
print "baz";
}
}
EOF;
eval( $code );
}
C::bar();
$o = new C;
if ( $o instanceof $x )
{
print "WIN!\n";
}
--->barWIN!
However, there is a more important question here:
Why the hell would you want to extend a different class at runtime
Anybody using your code will want to hold you down and whip you for that.
( Alternatively, if you're into whipping, do that eval trick )
I know this question was asked a long time ago, but the answer is relatively simple.
Assuming you want to extend class foo if class foo exists, or class bar if it doesn't, you'd use:
if(!class_exists('foo')) {
class foo extends bar {
function __construct() {
parent::__construct();
}
}
}
class myclass extends foo{
//YOUR CLASS HERE
}
Using PHP overloading you can accomplish this to a certain extent.
class variable_class {
public $orginalBaseClass;
public $orginalArgs;
public function __construct() {
// Get constructor parameters.
$this->orginalArgs = func_get_args();
// Get class name from args or 3rd party source.
$classname = 'stdClass';
// Pass along args to new class.
$this->orginalBaseClass = new $classname($this->orginalArgs);
}
public function __call($name, $arguments) {
// Pass all method calls to the orginalBaseClass.
return call_user_func_array(array($this->orginalBaseClass, $name), $arguments);
}
}
I'm using this pattern inside a Drupal module for prefetching data from the cache.
I don't see how this would be particularly useful, but to answer your question... no. There's no way to dynamically do that because the generated class has to be instantiated before the variable is evaluated (if that makes sense).
To put it simply: The class must exist before the code can be properly executed.
If you don't have too many values for $blah, you could extend each one in a different file then require_once "classes/foo_$blah.php"
Otherwise, you're stuck with the eval() solution... good luck with that... :)
I assume that this is for ease-of-maintenance, right? Extending a class at run time really is pretty crazy.
class SuperClassOne { /* code */ }
class SuperClassTwo { /* code */ }
class IntermediateClass extends SuperClassOne { /* empty! */ }
class DescendantClassFoo extends IntermediateClass{ }
class DescendantClassBar extends IntermediateClass{ }
class DescendantClassBaz extends IntermediateClass{ }
Then, when you want to change all your DescendantClass* classes, you just have to change what the IntermediateClass extends:
class IntermediateClass extends SuperClassTwo { }
I tested something with defines and barking:
<?php
define("INHERIT",A);
class A{
public function bark(){
return "I'm A";
}
}
class B{
public function bark(){
return "I'm B";
}
}
class C extends INHERIT{}
//main?
$dog = new C();
echo $dog->bark();
?>
the output is:
Fatal error: Class 'INHERIT' not found
in D:\sites\inherit.php on line 15
so the answer for "are variable class extensions possible?" is: No.
you should have tried $$
$blah = 'foo1';
class foo2 extends $$blah {
//...
}
class foo1 {
//...
}
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
I have a class which initiates another class, i'm not concerned with having a reference to the object i only need the method and have to pass in new parameters.
class A {
__set .....
}
class B extends A {
$anotherA = new A;
$anotherA->myName = 'stackoverflow';
}
in short i'd like to have class B extend A, init a new instance of A but i don't want to have to type "new" everytime, i've seen the following syntax:
B::A // something like that
but not sure if how to use it or if that would do what i'm trying to do?
What you could do is define a static method on the class that returns the new instance. It's basically a 'shortcut', but it does exactly the same in the background.
class C {
public static function instance()
{
return new C();
}
public function instanceMethod()
{
echo 'Hello World!';
}
}
Now you can call it like:
C::instance()->instanceMethod();
Here are some examples of static functions - they can be called without using 'new A' or 'new B'.
class A {
static function message($msg = 'I am Alpha') {
echo "hi there, $msg\n";
}
}
class B {
static function message() {
A::message("I am Beta");
}
}
A::message();
B::message();
I would create the instance of A in B's constructor, then you can instantiate B using either its constructor or static B::create(), which just acts as a shortcut. You could make the constructor private if you wanted all instantiation go through create().
class A {
// __set .....
}
class B extends A {
public function __construct() {
parent::__construct();
$anotherA = new A;
$anotherA->myName = 'stackoverflow';
}
public static function create() {
return new self();
}
}
new B();
B::create();
Since you are extending A in B, you could call the method of class A:
class B extends A {
public function someMethod() {
parent::someMethodName();
}
}
Alternatively, you could create a static method in the class:
class A {
public static function someStaticMethod() { ... }
}
A::someStaticMethod();
If you really want a new instance of A, you have to use the new operator. That's what it is for.
Is something like the following possible in PHP?
$blah = 'foo1';
class foo2 extends $blah {
//...
}
class foo1 {
//...
}
This gives an error.
I want to dynamically set $blah so I can extend whatever class I want.
Edit: The reason for wanting to do this because I wanted to use a function out of another class in a related class. In the end it would have been something like:
Final extends foo1 extends foo2 extends foo3 extends foo4 extends parent { ... }
In the end I decided to instantiate the other class within the class and use it. Not the best options because they both you 2 of the same classes, but this won't be used that often, so it will work for now.
You're assuming here php executes top to bottom, but it doesn't quite work like that:
<?php
foo(); # works
function foo(){
print "bar";
}
<?php
foo(); #dies
if( $i == 1 )
{
function foo(){
print "bar";
}
}
<?php
$i = 1;
if( $i == 1 )
{
function foo(){
print "bar";
}
}
foo(); #works
Now, although you can conditionally create classes:
<?php
class A { }
class B { }
if( false ){
class C extends B {
public static function bar(){
print "baz";
}
}
}
C::bar(); # dies
You cant instantiate one at runtime from a variable:
<?php
class A { }
class B { }
$x = 'B';
if( false ){
class C extends $x {
public static function bar(){
print "baz";
}
}
}
C::bar();
---> Parse error: syntax error, unexpected T_VARIABLE, expecting T_STRING in /tmp/eg.php on line 7
There is a way to do it with Eval, but you really don't want to go there:
<?php
class A { }
class B { }
$x = 'B';
if( true ){
$code =<<<EOF
class C extends $x {
public static function bar(){
print "baz";
}
}
EOF;
eval( $code );
}
C::bar();
$o = new C;
if ( $o instanceof $x )
{
print "WIN!\n";
}
--->barWIN!
However, there is a more important question here:
Why the hell would you want to extend a different class at runtime
Anybody using your code will want to hold you down and whip you for that.
( Alternatively, if you're into whipping, do that eval trick )
I know this question was asked a long time ago, but the answer is relatively simple.
Assuming you want to extend class foo if class foo exists, or class bar if it doesn't, you'd use:
if(!class_exists('foo')) {
class foo extends bar {
function __construct() {
parent::__construct();
}
}
}
class myclass extends foo{
//YOUR CLASS HERE
}
Using PHP overloading you can accomplish this to a certain extent.
class variable_class {
public $orginalBaseClass;
public $orginalArgs;
public function __construct() {
// Get constructor parameters.
$this->orginalArgs = func_get_args();
// Get class name from args or 3rd party source.
$classname = 'stdClass';
// Pass along args to new class.
$this->orginalBaseClass = new $classname($this->orginalArgs);
}
public function __call($name, $arguments) {
// Pass all method calls to the orginalBaseClass.
return call_user_func_array(array($this->orginalBaseClass, $name), $arguments);
}
}
I'm using this pattern inside a Drupal module for prefetching data from the cache.
I don't see how this would be particularly useful, but to answer your question... no. There's no way to dynamically do that because the generated class has to be instantiated before the variable is evaluated (if that makes sense).
To put it simply: The class must exist before the code can be properly executed.
If you don't have too many values for $blah, you could extend each one in a different file then require_once "classes/foo_$blah.php"
Otherwise, you're stuck with the eval() solution... good luck with that... :)
I assume that this is for ease-of-maintenance, right? Extending a class at run time really is pretty crazy.
class SuperClassOne { /* code */ }
class SuperClassTwo { /* code */ }
class IntermediateClass extends SuperClassOne { /* empty! */ }
class DescendantClassFoo extends IntermediateClass{ }
class DescendantClassBar extends IntermediateClass{ }
class DescendantClassBaz extends IntermediateClass{ }
Then, when you want to change all your DescendantClass* classes, you just have to change what the IntermediateClass extends:
class IntermediateClass extends SuperClassTwo { }
I tested something with defines and barking:
<?php
define("INHERIT",A);
class A{
public function bark(){
return "I'm A";
}
}
class B{
public function bark(){
return "I'm B";
}
}
class C extends INHERIT{}
//main?
$dog = new C();
echo $dog->bark();
?>
the output is:
Fatal error: Class 'INHERIT' not found
in D:\sites\inherit.php on line 15
so the answer for "are variable class extensions possible?" is: No.
you should have tried $$
$blah = 'foo1';
class foo2 extends $$blah {
//...
}
class foo1 {
//...
}