在 php 中调用类方法(带构造函数)而不实例化对象

Posted

技术标签:

【中文标题】在 php 中调用类方法(带构造函数)而不实例化对象【英文标题】:calling class method (with constructors) without object instantiation in php 【发布时间】:2011-03-07 03:31:41 【问题描述】:

我已经看过并尝试过,但我找不到答案。

php 中,是否可以调用类的成员函数(当该类需要构造函数来接收参数时)而不将其实例化为对象?

一个代码示例(给出错误):

<?php

class Test 
    private $end="";

    function __construct($value) 
        $this->end=$value;
    

    public function alert($value) 
        echo $value." ".$this->end;
    


//this works:
$example=new Test("world");
$example->alert("hello");

//this does not work:
echo Test("world")::alert("hello");

?>

【问题讨论】:

我以为 echo Test::__construct("world")::alert("hello");可能有效,但它没有,叹息 将 alert() 设置为静态函数就可以了。 【参考方案1】:

为此你可以做一个

https://www.php.net/manual/en/reflectionclass.newinstancewithoutconstructor.php

反射你的类并在没有构造函数的情况下触发新实例。

这里是一个示例代码:

<?php

class Test 
    private $end="";

    function __construct($value) 
        $this->end=$value;
    

    public function alert($value) 
        echo $value." ".$this->end;
    

    public function end($value) 

        $this->end = $value;        

        return $this; // return Test object so that you can chain to other function method.
    


// Solution #1:
// reflect your class.
$reflector = new \ReflectionClass('Test');

// Then create a new instance without Constructor.
// This will ignore the constructor BUT it will create a new instance of class Test.
$say = $reflector->newInstanceWithoutConstructor();

// use end method that will return the Test object, then you can chain the alert()
$say->end('World!')->alert("Hello"); // output: Hello World!

?>

【讨论】:

【参考方案2】:
// this does not work:
echo Test("world")::alert("hello");

// works, as you are calling not to an object of the class, but to its namespace
echo Test::alert("hello");

【讨论】:

【参考方案3】:

不幸的是 PHP 不支持这样做,但你是一个有创意的人:D

您可以使用“工厂”,示例:

<?php

class Foo

   private $__aaa = null;

   public function __construct($aaa)
   
      $this->__aaa = $aaa;
   

   public static function factory($aaa)
   
      return new Foo($aaa);
   

   public function doX()
   
      return $this->__aaa * 2;
   


Foo::factory(10)->doX();   // outputs 20

【讨论】:

我认为行不通。因为你不能在不创建任何对象的情况下引用 $this。【参考方案4】:

只需这样做(在 PHP >= 5.4 中):

$t = (new Test("Hello"))->foo("world");

【讨论】:

【参考方案5】:

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

$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');

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

【讨论】:

【参考方案6】:

您不能在没有实例的情况下调用实例级方法。你的语法:

echo Test("world")::alert("hello");

没有多大意义。要么您正在创建一个内联实例并立即丢弃它,要么alert() 方法没有隐式this 实例。

假设:

class Test 
  public function __construct($message) 
    $this->message = $message;
  

  public function foo($message) 
    echo "$this->message $message";
  

你可以这样做:

$t = new Test("Hello");
$t->foo("world");

但 PHP 语法不允许:

new Test("Hello")->foo("world");

否则将是等价的。 PHP 中有几个这样的例子(例如,在函数返回时使用数组索引)。就是这样。

【讨论】:

我正在创建一个内联实例并立即丢弃它。我不明白为什么我需要为这个进程分配一个变量......这就是 PHP/OOP 的方式吗?

以上是关于在 php 中调用类方法(带构造函数)而不实例化对象的主要内容,如果未能解决你的问题,请参考以下文章

java怎么调用带参数构造函数

hibernate 为什么持久化类时必须提供一个不带参数的默认构造函数

在php中,子类extends继承了父类,当子类和父类同时存在构造函数__construct先执行哪一个呢?

如何让 PHP 类构造函数调用其父级的父级构造函数?

PHP动态获取类构造函数并调用它来创建一个新实例[重复]

什么时候调用构造函数?