147

我想在 PHP 中创建一个静态类,并让它像在 C# 中一样,所以

  1. 构造函数在第一次调用类时自动调用
  2. 无需实例化

这种东西...

static class Hello {
    private static $greeting = 'Hello';

    private __construct() {
        $greeting .= ' There!';
    }

    public static greet(){
        echo $greeting;
    }
}

Hello::greet(); // Hello There!
4

6 回答 6

211

您可以在 PHP 中使用静态类,但它们不会自动调用构造函数(如果您尝试调用self::__construct(),则会收到错误消息)。

因此,您必须创建一个initialize()函数并在每个方法中调用它:

<?php

class Hello
{
    private static $greeting = 'Hello';
    private static $initialized = false;

    private static function initialize()
    {
        if (self::$initialized)
            return;

        self::$greeting .= ' There!';
        self::$initialized = true;
    }

    public static function greet()
    {
        self::initialize();
        echo self::$greeting;
    }
}

Hello::greet(); // Hello There!


?>
于 2009-01-22T10:39:12.947 回答
56

除了 Greg 的回答,我建议将构造函数设置为私有,这样就不可能实例化该类。

所以在我看来,这是一个基于 Greg 的更完整的例子:

<?php

class Hello
{
    /**
     * Construct won't be called inside this class and is uncallable from
     * the outside. This prevents instantiating this class.
     * This is by purpose, because we want a static class.
     */
    private function __construct() {}
    private static $greeting = 'Hello';
    private static $initialized = false;

    private static function initialize()
    {
        if (self::$initialized)
            return;

        self::$greeting .= ' There!';
        self::$initialized = true;
    }

    public static function greet()
    {
        self::initialize();
        echo self::$greeting;
    }
}

Hello::greet(); // Hello There!


?>
于 2012-07-20T09:49:39.060 回答
24

你可以拥有那些类似“静态”的类。但我想,缺少一些非常重要的东西:在 php 中你没有应用程序周期,所以你不会在整个应用程序中获得真正的静态(或单例)......

参见PHP 中的单例

于 2009-01-22T10:44:34.903 回答
5
final Class B{

    static $staticVar;
    static function getA(){
        self::$staticVar = New A;
    }
}

b 的结构称为 singeton 处理程序,您也可以在 a 中执行此操作

Class a{
    static $instance;
    static function getA(...){
        if(!isset(self::$staticVar)){
            self::$staticVar = New A(...);
        }
        return self::$staticVar;
    }
}

这是单例使用 $a = a::getA(...);

于 2010-08-24T09:37:29.973 回答
3

我通常更喜欢编写常规的非静态类并使用工厂类来实例化对象的单个(sudo static)实例。

这种方式构造函数和析构函数正常工作,如果我愿意,我可以创建额外的非静态实例(例如第二个数据库连接)

我一直使用它,对于创建自定义数据库存储会话处理程序特别有用,因为当页面终止时,析构函数会将会话推送到数据库。

另一个优点是您可以忽略调用顺序,因为一切都将按需设置。

class Factory {
    static function &getDB ($construct_params = null)
    {
        static $instance;
        if( ! is_object($instance) )
        {
            include_once("clsDB.php");
            $instance = new clsDB($construct_params);   // constructor will be called
        }
        return $instance;
    }
}

数据库类...

class clsDB {

    $regular_public_variables = "whatever";

    function __construct($construct_params) {...}
    function __destruct() {...}

    function getvar() { return $this->regular_public_variables; }
}

任何你想使用它的地方只需调用...

$static_instance = &Factory::getDB($somekickoff);

然后将所有方法视为非静态的(因为它们是)

echo $static_instance->getvar();
于 2012-12-30T21:43:21.180 回答
2

对象不能静态定义,但这有效

final Class B{
  static $var;
  static function init(){
    self::$var = new A();
}
B::init();
于 2010-11-29T15:46:27.753 回答