【问题标题】:calling class method (with constructors) without object instantiation in php在 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() 设置为静态函数就可以了。

标签: php class constructor methods instantiation


【解决方案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 的方式吗?
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-05
          • 2014-09-23
          相关资源
          最近更新 更多