tags:

views:

100

answers:

3

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.

+4  A: 

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 :)

atk
Exactly, this is the sort of language feature that really shouldn't exist. Reflection based systems are hard enough to follow, and they at least have very explicit rules they have to follow.
LorenVS
@atk - +1 agreed, just looking at the first block of code gave me a headache.
karim79
The idea behind this was if $test held a class that has one function accessed most of the time, I could create a helper function that would make it easier to type. But I get your point.
Chacha102
The first block of code gave you a headache? Function pointers give you a headache? Granted it's probably not the best way of implementing it, but that's exactly what it is.
Matthew Scharley
@Matthew Scharley - exactly, there's nothing about it that differentiates it from an ordinary variable, $foo(); looks like it shouldn't work, but I know that it does. Headache!
karim79
I would disagree, function pointers are strongly typed and will break if the method name is changed. Modern IDE's would give you features like FindAllReferences which would tell you exactly where a function is used (even if it is assigned to a function pointer).
LorenVS
@LorenVS - Every language gives its own opportunities for unclear code, and clear code can be written in every language (even Perl :) ). The feature of function pointers can be very useful, and can make some source code very elegant and very clean, so I don't think it should be completely removed. It just needs to be used carefully.
atk
If you've ever worked with languages in which functions are objects, this would certainly seem familiar. And it's not that hard to maintain either, provided that you write it well, as it happens with any programming problem.
Ionuț G. Stan
@Inout G Stan - My issue is not with using the function pointer, but with overloading a single variable for two distinct uses. $test is used both as an object pointer and as a function pointer. Even in a language where functions are objects, this would still be confusing - it forces dependencies upon all related code to be absolutely sure that the myClass object currently has $test in an expected state, or risk crashing. Such dependencies are very easy to miss, which causes maintenance issues. If fcns were full objects, it would still be advisable to keep use clearly named variables/
atk
+2  A: 

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 :(
Ionuț G. Stan
+1  A: 

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. ;)
deceze