tags:

views:

399

answers:

5

Below is an example class hierarchy and code. What I'm looking for is a way to determine if 'ChildClass1' or 'ChildClass2' had the static method whoAmI() called on it without re-implementing it in each child class.

<?php

abstract class ParentClass {

    public static function whoAmI () {

        // NOT correct, always gives 'ParentClass'
        $class = __CLASS__;

        // NOT correct, always gives 'ParentClass'. 
        // Also very round-about and likely slow.
        $trace = debug_backtrace();
        $class = $trace[0]['class'];

        return $class;
    }
}

class ChildClass1 extends ParentClass {

}

class ChildClass2 extends ParentClass {

}

// Shows 'ParentClass'
// Want to show 'ChildClass1'
print ChildClass1::whoAmI(); 
print "\n";

// Shows 'ParentClass'
// Want to show 'ChildClass2'
print ChildClass2::whoAmI();
print "\n";
+7  A: 

I believe what you're referring to is a known php bug. Php 5.3 is aiming to address this issue with a new Late Static Binding feature.

http://www.colder.ch/news/08-24-2007/28/late-static-bindings-expl.html

Kent Fredric
A: 

No. Wait for PHP 5.3.

develop7
+1  A: 

Class identification is often a symptom of not well understood Polymorphism.

The clients of ChildClass1 and ChildClass2 shouldn't need to distinguish between them.

There's no place where any class should ask about someObject.whoAmI().

Whenever you have the urge to write if someObject.whoAmI() == 'ChildClass1' { do X(someObject) } you should really add an X() method to the ParentClass with various implementations in the various ChildClasses.

This kind of "run-time type identification" can almost always be replaced with properly polymorphic class designs.

S.Lott
@S.Lott I fully agree that such a method would be a leaky abstraction if used in real code. In this case the method is just there to provide an understandable sample. My reason for wanting to determine the child class is so that I can make use of static instance creation methods that are shared by all members of a class hierarchy, yet still call the appropriate child-constructor.
Adam Franco
+1  A: 

As of PHP 5.3 it'll be possible with the use of the static keyword, but for now it isn't possible.

Ben Dowling
+1  A: 

Now that PHP 5.3 is widely available in the wild, I wanted to put together a summary answer to this question to reflect newly available techniques.

As mentioned in the other answers, PHP 5.3 has introduced Late Static Binding via a new static keyword. As well, a new get_called_class() function is also available that can only be used within a class method (instance or static).

For the purpose of determining the class as was asked in this question, the get_called_class() function is appropriate:

<?php

abstract class ParentClass {

    public static function whoAmI () {
        return get_called_class();
    }

}

class ChildClass1 extends ParentClass {

}

class ChildClass2 extends ParentClass {

}

// Shows 'ChildClass1'
print ChildClass1::whoAmI(); 
print "\n";

// Shows 'ChildClass2'
print ChildClass2::whoAmI();
print "\n";

The user contributed notes for get_called_class() include a few sample implementations that should work in PHP 5.2 as well by making use of debug_backtrace().

Adam Franco