在PHP中,能否实例化一个对象并在同一行上调用一个方法?

在PHP中,能否实例化一个对象并在同一行上调用一个方法?,php,oop,Php,Oop,我想做的是这样的: $method_result = new Obj()->method(); <?php class test { function __call($func,$args) { echo "I am here - $func\n"; } } $a = new test(); $a->new( "My new class" ); ?> 而不是必须这样做: $obj = new Obj(); $method_result =

我想做的是这样的:

$method_result = new Obj()->method();
<?php
class test
{

function __call($func,$args)
{
    echo "I am here - $func\n";
}

}

    $a = new test();
    $a->new( "My new class" );
?>
而不是必须这样做:

$obj = new Obj();
$method_result = $obj->method();

在我的具体案例中,结果对我来说并不重要。但是,有办法做到这一点吗?

不,这是不可能的。
您需要先将实例分配给变量,然后才能调用它的任何方法

如果你真的不想这样做,你可以像罗普斯塔建议的那样使用工厂:

class ObjFactory{
  public static function newObj(){
      return new Obj();
  }
}
ObjFactory::newObj()->method();

可以使用静态工厂方法生成对象:

ObjectFactory::NewObj()->method();
那么:

$obj = new Obj(); $method_result = $obj->method(); // ?

:p

你不能做你要求的事;但是你可以“作弊”,因为在PHP中,你可以有一个与类同名的函数;这些名字不会冲突

因此,如果您声明了这样一个类:

class Test {
    public function __construct($param) {
        $this->_var = $param;
    }
    public function myMethod() {
        return $this->_var * 2;
    }
    protected $_var;
}
然后,您可以声明一个函数,该函数返回该类的实例,并且与该类具有完全相同的名称:

function Test($param) {
    return new Test($param);
}
现在,可以像您所问的那样使用一行程序了——唯一的问题是您正在调用函数,因此没有使用新的:

$a = Test(10)->myMethod();
var_dump($a);
它起作用了:在这里,我得到:

int 20
作为输出


更好的是,您可以在函数中添加一些phpdoc:

/**
 * @return Test
 */
function Test($param) {
    return new Test($param);
}
这样,您甚至可以在IDE中得到提示——至少在EclipsePDT2.x中是这样;请参阅screeshot:



编辑2010-11-30:仅供参考,几天前提交了一份新的RFC,提议将此功能添加到PHP的未来版本中

请参阅:请求注释:实例和方法调用/属性访问

因此,在PHP 5.4或其他未来版本中,可能会执行以下操作:

(new foo())->bar()
(new $foo())->bar
(new $bar->y)->x
(new foo)[0]

通过定义标识函数,您可以更普遍地执行此操作:

function identity($x) {
    return $x;
}

identity(new Obj)->method();

这样,您就不需要为每个类定义函数

我也在寻找一个单行程序来实现这一点,作为将日期从一种格式转换为另一种格式的单个表达式的一部分。我喜欢在一行代码中执行此操作,因为这是一个单一的逻辑操作。因此,这有点神秘,但它允许您在一行中实例化和使用日期对象:

$newDateString = ($d = new DateTime('2011-08-30') ? $d->format('F d, Y') : '');
将日期字符串从一种格式转换为另一种格式的另一种方法是使用帮助函数来管理代码的OO部分:

function convertDate($oldDateString,$newDateFormatString) {
    $d = new DateTime($oldDateString);
    return $d->format($newDateFormatString);
}

$myNewDate = convertDate($myOldDate,'F d, Y');

我认为面向对象的方法是很酷和必要的,但有时会很乏味,需要太多的步骤来完成简单的操作。

您要求的功能可以从PHP5.4获得。以下是PHP 5.4中的新功能列表:

以及新功能列表中的相关部分:

已添加实例化时的类成员访问权限,例如(new Foo)->bar()。


我认为这是一个老生常谈的问题,但我认为有一点应该提到:

名为“\uuuCall()”的特殊类方法可用于在类内创建新项。您可以这样使用它:

$method_result = new Obj()->method();
<?php
class test
{

function __call($func,$args)
{
    echo "I am here - $func\n";
}

}

    $a = new test();
    $a->new( "My new class" );
?>
因此,您可以欺骗PHP在顶级类(或任何真正的类)中生成一个“新”命令,并将include命令放入_call()函数中,以包含您请求的类。当然,您可能需要测试$func,以确保它是发送到_call()命令的“新”命令,并且(当然)由于_call()的工作方式,您还可以使用其他命令。

我们可以这样做

$method_result = (new Obj())->method();

皮姆的回答是正确的。或者,如果您不希望创建对象的实例,可以使用静态函数。使用此函数,我们将强制使用
公共静态函数
,而不是
公共函数
。建议使用static?很好的解决方案,因为它强调了这个限制的愚蠢:)顺便说一句,如果你没有使用5.4(你可能没有),你可以定义一个helper函数,它只返回一个对象到chain stuff。。。带有($obj){return$obj;}的函数(从laravel:P获得技巧)。。然后您可以使用(new Obj)->method()顺便说一句,如果您发现自己经常这样做,那么值得考虑是否应该将
my_method
声明为
static
。请注意,这也意味着您可以根据需要执行
(new Foo)->property
。请注意,您还不能以这种方式分配属性。(新Foo)->property='property'@从逻辑上讲,这是有道理的;该对象仅在语句
(new Foo)->property
期间存在-您存储的值无处可去,因为在此之后该对象将不再存在,因为它不存储在任何位置。@CMCDRANGKAI您可以通过调用相应的设置器以这种方式分配属性,您只需将
return$this
添加到setters即可。这也会让你的链条设定器。我有一个问题。除了能够重用对象之外,在单独的行上声明对象并将其保存到变量有什么好处吗?不需要单独的工厂;同一类中的静态方法将完成相同的任务。