Appologies if this is a duplicate, could not seem to either search for the right words or does not exist (somehow i doubt this and likely i am making an obvious mistake).
<?php
class Test {
public $var = true;
public function test() {
var_dump($this->var);
}
}
class Testing extends Test {
public $var = false;
}
$test = new Testing();
$test->test();
Simple enough program, base class, with a method, inheriting class with an override, then calling the base method.
Gives output, False, line return False,
What? Why twice? Exactly my question good man.
bool(false)
bool(false)
Thanks
This happened because your method name same with class name.
Methods like this been used as a class constructor in PHP4 - php.net
They still works, when you have not __construct method for compatibility.
Related
According to php, class::self always points to the class itself, but as I wrote down these codes, something strange happens:
class C_foo{
function foo() { return "foo() from C_foo"; }
function bar() { echo self::foo(); }
}
class C_bar extends C_foo{
function foo() { return "foo() from C_bar"; }
}
C_foo::bar();
C_bar::bar();
I thought the output would have been:
foo() from C_foo
foo() from C_bar
But in fact:
foo() from C_foo
foo() from C_foo
It means that the self in parent class does NOT exactly inherit into the child, it works more like to this:
foo() {return parent::foo();}
Is that a feature from php or is it a bug? Or is it mean to be like this?
Otherwise, such thing is occurred as I tried to tell a class create objects from itself, the code is something like this:
class Models {
function find($exp) {
...
...
$temp_model = new self();
...
...
}
}
class Something extends Models {...}
$somethings = Something::find("...");
Maybe someone would ask, "why don't you set a variable with the value of class, and use the variable as the __construction function?"
Like this:
...
...
function find($exp) {
...
...
$class_name = __class__;
$temp_model = new $class_name();
...
...
}
...
In fact I did that, and got a even more weird result:
It works only when the class does not have any property or function but find(), or an error telling me a variable shows off where a function sould exist would jump out.
It sounds like you're describing the PHP feature known as 'late static binding'.
PHP provides two syntaxes: self:: and static::.
static was introduced in PHP 5.3 because a lot of people expected self to work the you're describing.
See the PHP manual for more: http://php.net/manual/en/language.oop5.late-static-bindings.php
You can also use the syntax new self() or new static() to create new instances:
$parent = new self();
$child = new static();
This is because the class which receives the methods of the parent is of that class. So:
$bar is Bar, therefore self:: refers to Bar, not to Foo. Even though that method is from Foo.
This may be different from Java, but it probably indicates how PHP is doing inheritance internally.
In PHP, classes are not object. Because of that, there is no inheritance of static methods (actually, they are similar to global functions).
So, when C_foo says self, it always means C_foo (even if you called a method from C_bar).
If you want create instances from an abstract class method, you should try the Factory pattern.
I have a class that looks something like this:
class Foo {
protected $_arr = array();
public function has($key) {
return array_key_exists($key, $this->_arr);
}
public function add($key, $val) {
$this->_arr[$key] = $val;
}
}
For my PHPUnit tests for these methods, the only way I can think if to test add() is by asserting that has() returns TRUE for the same key after adding it. This makes my testAdd() test dependent on my testHas() test. Conversely, the only way I can think of to test has() is basically doing the exact same steps, but this would make this test dependent on an already dependent test, producing a chicken and egg type problem.
Am I going about this the wrong way? What's a better method for testing stuff like this?
Instead of writing one-test-per-method, design your tests around the functionality the class must provide. You'll have tests that exercise multiple methods, but that's fine because it indicates to the developer that those methods are related. This is where Test Driven Development--where you write the tests while designing the contract for the class before writing the code for the class--really shines.
class FooTest extends PHPUnit_Framework_TestCase
{
function testStartsEmpty() {
$foo = new Foo;
self::assertFalse($foo->has('bar'));
}
function testAddStoresKeys() {
$foo = new Foo;
$foo->add('bar', 'baz');
self::assertTrue($foo->has('bar'));
}
function testAddStoresKeysWithNullValues() {
$foo = new Foo;
$foo->add('bar', null);
self::assertTrue($foo->has('bar'));
}
function testAddStoresValues() {
$foo = new Foo;
$foo->add('bar', 'baz');
self::assertEquals('baz', $foo->get('bar')); // fatal error
}
}
Now that testAddStoresValues() fails, it's time to implement a method to get the value for a given key: Foo::get($key).
PHPUnit allows testing of non-public members.
However, using $sut->has() to find out whether $sut->add() worked is perfectly fine. Also, when you test $sut->add(), you dont need to write a separate test for $sut->has() as well, because it's covered in the $sut->add() test already. Just add a #covers annotation.
In reference to the long dicussions in the comments to #Gordon s answer:
The unit in unit testing is the object not the method! You don't want to test methods in isolation from the other methods of the objects. (If you wanted to do so just use functions ;) ) - It's really important to test how the object behaves and if it does the expected think when called and not how the methods interact internally.
I've recently written a blog post explaining why it is important to not test single methods in isolation:
http://edorian.posterous.com/the-unit-in-unit-testing
Quoting from my post:
Unit testing, in PHP, is about testing the observable behaviors of a class
Most importantly:
Observable from the outside! Nobody cares about the internal state of a class if it never changes the outcome of a method call.
Take this sample:
public function setValue($value) {
$this->value = $value;
}
public function execute() {
if (!$this->value) {
throw new Exception("No Value, no good");
}
return $value * 10; // business logic
}
It sounds trivial but the distinction is important and more easy to overlook when looking at bigger classes.
What do we test there?
IF we don’t setValue AND then call execute an exception is thrown!
IF we DO setValue AND then call execute we get an computed result
So we are testing two behaviors of your class and not the methods in isolation!
IMO you can test behavior of the object. So you can test if has return false before and true after adding some stuff into collection.
I know that you can call functions using variable names like this:
$foo = "bar";
function bar()
{
echo "test";
}
$foo(); // echos test
I am wondering if in a class, an actual function overrides that.
If I had this class:
class myClass{
public $test;
public function __construct()
{
$this->test = new myOtherClass;
}
public function test()
{
echo "foo";
}
}
Would both of these work correctly?
$obj->test(); // echo foo
$obj->test->method(); // access a method of myOtherClass
Edit: The original idea for this was that myOtherClass held a class with one main function that was accessed all the time, and a few other less accessed ones. I could use test() to link the main function to the class so there is less typing. But given the first answer I'll probably stick away from that.
I don't know PHP well enough to answer your question, but I spent several years maintaining products and would like to point out a serious difficulty with maintainability with this. Consider that you have the question as to whether this will even work properly. Now consider that the person maintaining your code will (a) have the same question as you and (b) probably not read the whole class (unless it's a very small class). And if you're changing $test from outside the class, it will be even more difficult to understand.
While this is an interesting question, especially from an academic point of view, it's a terrible practice from a maintenance point of view. Please use different variable names for different purposes; for example, use $otherClass for the pointer to the other class and test() for the test function and your maintainers (including yourself, if you maintain your own code) will curse at you less :)
PHP allows different symbols with the same name. Object properties and methods are totally different things in PHP, unlike JavaScript and some other languages:
// all of them work OK
define('SomeClass', 'SomeClass');
function SomeClass () {}
class SomeClass {}
This causes ugly problems in PHP 5.3:
$foo = new StdClass;
$foo->bar = function () {
return "bar";
};
$foo->bar(); // does not work, unfortunately :(
You wrote:
$obj->test(); // echo foo
$obj->test->method(); // access a method of myOtherClass
Right, this is how it works. You're not using anything variable in there.
$obj->test; // member variable $test of $obj
$obj->test(); // method test() of $obj
$obj->$test(); // variable function, result depends on content of $test
$obj->test()->otherTest(); // invokes otherTest() on an object
// returned by $obj->test()
$foo = 'test';
$bar = 'otherTest';
$obj->$foo()->$bar(); // same as above, but please, for the love of God,
// don't ever use this. ;)
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";
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
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().
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.
As of PHP 5.3 it'll be possible with the use of the static keyword, but for now it isn't possible.
No. Wait for PHP 5.3.
There was an interesting question in a practice test that I did not understand the answer to. What is the output of the following code:
<?php
class Foo {
public $name = 'Andrew';
public function getName() {
echo $this->name;
}
}
class Bar extends Foo {
public $name = 'John';
public function getName() {
Foo::getName();
}
}
$a = new Bar;
$a->getName();
?>
Initially, I thought this was produce an error because static methods can not reference $this (atleast in PHP5). I tested this myself and it actually outputs John.
I added Foo::getName(); at the end of the script and did get the error I was expecting. So, what changes when you call a static method from within a class that extends the class you're calling from?
Would anyone mind explaining in detail exactly what is going on here?
Foo::getName() is using an older PHP4 style of scope resolution operator to allow an overridden method to be called.
In PHP5 you would use parent::getName() instead
It's useful if you want to extend, rather than completely override the behaviour of the base class, e.g. this might make it clearer
class Bar extends Foo {
public $name = 'John';
public function getName() {
echo "My name is ";
parent::getName();
}
}
If you call the static method bound to the other object, the method is executed in the context of the current object. Which allows access to the $this-object.
Better way to call the superclass-method from inside the subclass would be:
parent::getName();
$this to the object in whose context the method was called. So: $this is $a->getName() is $a. $this in $fooInstance->getName() would be $fooInstance. In the case that $this is set (in an object $a's method call) and we call a static method, $this remains assigned to $a.
Seems like quite a lot of confusion could come out of using this feature. :)
When you call $a->getName() you're referencing a specific object, $a, which is of class Bar and so returns "John".
Foo::getName() isn't valid outside the function because there's no specific object.
I'm not sure it works in PHP, but if you cast the object to the superclass as in (Foo)$a->getName() then you'd get "Andrew" as your result. You'd still be talking about the specific object ($a) but in this case of type Foo. (Note you wouldn't generally want to do this)
Sometimes programmers are better at explaining things in code than in English!
The first thing going on here is the concept of overloading. When you instantiate Bar, it's getName() method overloads the method of the same name in Foo.
Overloading is a powerful and important part of OOD.
However, it is often useful to be able to call the version of a method that exists in the Parent class (Foo).
Here's an example:
class Dog
{
public function getTag()
{
return "I'm a dog.";
}
}
class Skip extends dog
{
public function getTag()
{
return Dog::getTag() . " My name is Skip.";
// I'm using Dog:: because it matches your example. However, you should use parent:: instead.
}
}
$o = new Skip();
echo $o->getTag(); // Echo's: "I'm a dog. My name is Skip."
Clearly this is a very parochial example but it illustrates a point.
Your base class is the most general implementation of a Type. In this case, it's "Dog." You want to put information in this base class that is common to all instances of that Type. This prevents duplication in each of the Derived classes (like "Skip").
Your script is taking advantage of this feature, perhaps inadvertently.