calling a method of an object at instance creation

前端 未结 5 1012
[愿得一人]
[愿得一人] 2020-12-19 18:08

In PHP why can\'t I do:

class C
{
   function foo() {}
}

new C()->foo();

but I must do:

$v = new C();
$v->foo();


        
相关标签:
5条回答
  • 2020-12-19 18:19

    From PHP 5.4 you CAN do: (new Foo())->someMethod();

    0 讨论(0)
  • 2020-12-19 18:25

    You should not be able to execute code like

    new C()->foo();

    in other languages, at least not as long as that language accurately follows logic. The object is not just created using C(), but with the full new C(). Therefore, you should hypothetically be able to execute that code if you include another pair of parentheses: (new C())->foo();

    (Be warned: I haven't tested the above, I'm just saying it should hypothetically work.)

    Most languages (that I've encountered) deal with this situation the same way. C, C#, Java, Delphi...

    0 讨论(0)
  • 2020-12-19 18:26

    In PHP, you can't call an arbitrary method on a freshly created object like new Foo()->someMethod();

    Sorry, but that's the way it is.

    But you could build a work around like this:

    <?php
    class CustomConstructor
    {
      public static function customConstruct($methodName)
      {
        $obj = new static; //only available in PHP 5.3 or later
        call_user_method($methodName, $obj);
        return $obj;
      }
    }
    

    Extend CustomContructor like this:

    class YourClass extends CustomConstructor
    {
      public function someCoolMethod()
      {
        //cool stuff
      }
    }
    

    And instantiate them like this:

    $foo = YourClass::customConstruct('someCoolMethod');
    

    I have not tested it but this or something like it should work.

    Correction: This will only work in PHP 5.3 and later since late static binding is required.

    0 讨论(0)
  • 2020-12-19 18:34

    Starting from PHP 5.4 you can do

    (new Foo)->bar();
    

    Before that, it's not possible. See

    • One of many question asking the same on SO
    • Discussion on PHP Internals
    • Another Discussion on PHP Internals
    • Relevant Feature Request in BugTracker

    But you have some some alternatives

    Incredibly ugly solution I cannot explain:

    end($_ = array(new C))->foo();
    

    Pointless Serialize/Unserialize just to be able to chain

    unserialize(serialize(new C))->foo();
    

    Equally pointless approach using Reflection

    call_user_func(array(new ReflectionClass('Utils'), 'C'))->foo();
    

    Somewhat more sane approach using Functions as a Factory:

    // global function
    function Factory($klass) { return new $klass; }
    Factory('C')->foo()
    
    // Lambda PHP < 5.3
    $Factory = create_function('$klass', 'return new $klass;');
    $Factory('C')->foo();
    
    // Lambda PHP > 5.3
    $Factory = function($klass) { return new $klass };
    $Factory('C')->foo();
    

    Most sane approach using Factory Method Pattern Solution:

    class C { public static function create() { return new C; } }
    C::create()->foo();
    
    0 讨论(0)
  • 2020-12-19 18:34

    I tried this and was successful -

    <?php
    
    $obj = new test("testFunc");
    
    class test{
        function __construct($funcName){
            if(method_exists($this, $funcName)){
                self::$funcName();
            }
        }
    
        function testFunc(){
            echo "blah";
            return $this;
        }
    }
    
    ?>
    
    0 讨论(0)
提交回复
热议问题