【问题标题】:What are good reasons to use static methods in PHP?在 PHP 中使用静态方法的充分理由是什么?
【发布时间】:2011-06-08 19:24:40
【问题描述】:

有没有人有使用静态方法代替动态方法的好例子?

【问题讨论】:

    标签: php oop static-methods


    【解决方案1】:

    单例:

    class SingletonClass {
        private static $instance;
        private function __construct() { }
        public function __clone() {
            trigger_error('Clone is not allowed.', E_USER_ERROR);
        }
        public static function init() {
            if (!isset(self::$instance)) {
                $c = __CLASS__;
                self::$instance = new $c;
            }
            return self::$instance;
        }
        // other public, dynamic methods for singleton
    }
    
    $singleton = SingletonClass::init();
    

    跟踪实例数:

    class CountMe {
        public static $instances = 0;
        public function __construct() {
            CountMe::$instances++;
        }
        public function __destruct() {
            CountMe::$instances--;
        }
    }
    $a = new CountMe();
    $b = new CountMe();
    echo CountMe::$instances; // outputs 2
    

    【讨论】:

    • 有些东西不见了。为什么你使用 init() 而不是 __construct?为什么我应该调用 init() 而不是只使用我需要的方法并让类在 __construct 中创建它的实例?
    • 因为构造函数是私有的。这确保您不能自己创建类。您必须通过 init 方法,init 方法要么返回一个实例,要么创建一个实例并返回它。这样,您将始终只有一个类的实例。
    • 单身人士的全部目的就是:单身。这种结构可以防止创建一个对象的多个实例。
    • 换句话说:你不能这样做$var = new SingletonClass();,因为会抛出一个错误。但是静态方法可以做到这一点self::$instance = new $c;,因为它可以访问私有构造函数。
    • 最后,如果您有权访问__construct,则每次您想要获取它的实例时都必须实例化该类,因此:不是单例。
    【解决方案2】:

    当您不需要访问实例成员时。

    【讨论】:

      【解决方案3】:

      数据库连接将是静态函数的一个很好的用途。您不需要直接访问整个数据库对象,您只需要访问连接资源即可。所以你可以打电话

       $connection = new DatabaseConnection();
       StaticClass::setDatabase($connection);
       $result = StaticClass::getDatabaseConnection()->query();
      

      但如果您以后需要访问该类以进行存储或同一对象的多个实例,那么您就不想变成静态的。

      您的类现在也存在于全局范围内,因此您可以从任何类、任何范围、代码库中的任何位置访问它。

      function getUsers()
      {
           $users = StaticClass::getDatabaseConnection()->query('SELECT * FROM users');
      }
      

      【讨论】:

        【解决方案4】:

        在较少面向代码的性质中,这是我定义静态方法的方式(我将以银行为例): 如果你有一个银行课程并且想开一家新银行,你会使用:

        $b = new Bank;
        

        现在假设您想向这家银行添加一名新员工。只需调用:

        $b->addEmployee( 'Person' );
        

        由于您将操作应用于您创建的银行而不是拥有整个银行的公司,因此您使用会员方法。现在假设该公司交易了一些资产并赚钱。要更新他们的总金额,您可以这样称呼:

        Bank::addToCompanyBalance( 1000000 );
        

        请注意,由于该操作不只是应用于我们创建的银行,因此我们使用了静态方法。

        虽然这个例子过于简单,但我喜欢这个类比。在更程序化的情况下,静态成员有利于:

        单身人士

        class Singleton
            private static $instance;
        
            private function __construct() {}
            private function __clone() {}
        
            public static function getInstance() {
                if( !isset( self::$instance ) ) self::$instance = new IamOne;
                return( self::$instance );
            }
        }
        

        创建可能失败的类
        前任。文件处理程序类可能并不总是想创建一个新对象(比如传递的文件不存在或无法打开)。

        带有抽象类
        有些类可能不希望有实例(例如解释用户请求的路由器)。但是,抽象类可以静态调用,因此可以使用静态方法。

        【讨论】:

        • 这对我帮助很大。有时使用真实世界的示例(例如您的银行)确实很有帮助,而不是显示对不熟悉该概念的人可能没有任何意义的过度技术用例(*咳嗽*大多数 PHP.net 文档)。我刚刚开始学习使用类来制作插件,并想知道为什么人们使用静态与非静态方法和属性。
        【解决方案5】:

        示例:使用静态方法创建可能采用不同参数的对象实例。

        Class DBConnection
        {
            public static function createFromConfiguration(Configuration $config)
            {
                $conn = new DBConnection();
                $conn->setDsn($config->getDBDsn());
                $conn->setUser($config->getDBUser());
                $conn->setPassword($config->getDBPass());
        
                return $conn;
            }
        
            public static function newConnection($dsn, $user, $password)
            {
                $conn = new DBConnection();
                $conn->setDsn($dsn);
                $conn->setUser($user);
                $conn->setPassword($password);
        
                return $conn;
            }
        }
        

        【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2023-03-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-27
        相关资源
        最近更新 更多