PHP 5:const与static的区别

191

在 PHP 5 中,使用 conststatic 的区别是什么?

它们各自适用于何时?如果有的话,publicprotectedprivate 扮演了什么角色?

8个回答

213
在类的上下文中,静态变量具有类作用域(而不是对象作用域),但与const不同的是,它们的值可以被更改。
class ClassName {
    static $my_var = 10;  /* defaults to public unless otherwise specified */
    const MY_CONST = 5;
}
echo ClassName::$my_var;   // returns 10
echo ClassName::MY_CONST;  // returns 5
ClassName::$my_var = 20;   // now equals 20
ClassName::MY_CONST = 20;  // error! won't work.

对于常量(始终为public),public、protected和private无关紧要;它们仅适用于类变量,包括静态变量。

  • public static变量可以通过ClassName::$variable在任何地方访问。
  • protected static变量可以通过定义类或扩展类的方式通过ClassName::$variable访问。
  • private static变量只能通过定义类通过ClassName::$variable访问。

编辑:需要注意的是,PHP 7.1.0引入了指定类常量可见性的支持

30
我更喜欢使用self::$variable来表示受保护的静态变量和私有静态变量,因为我希望在类内部仅在开头提到一次类名。 - Lukman
4
好的,我会尽力进行翻译。 是的,说得好,我忘了提到如果在类内部引用时可以使用self关键字。我上面提供的例子是在类定义之外执行的,在这种情况下必须使用类名。 - Matt Huggins
非常好的答案,非常接近被采纳。您能否澄清一点:「公共、受保护和私有在常量方面是无关紧要的」- 为什么? 常量默认是全部公共的吗?全部私有的吗? - Chris Jacob
2
静态变量不需要 $ 吗?在定义中是这样的:static $my_var = 10; - Daniel W.
旧帖,但我想补充一些内容:请查看http://php.net/manual/en/language.variables.scope.php#language.variables.scope.static,其中解释了`static`变量在单例和递归函数中非常有用。因为您可以更改值,但变量只会初始化一次。请参见https://dev59.com/inVC5IYBdhLWcg3wtzqs以获取有关如何创建单例的进一步说明。对于我来说,这些都是我更喜欢使用静态变量的情况。 - Erik van de Ven

20

最后需要说明的一点是,const 常量总是静态的和公开的。这意味着您可以在类内部像这样访问 const 常量:

class MyClass
{
     const MYCONST = true;
     public function test()
     {
          echo self::MYCONST;
     }
}

从类的外部访问它应该像这样:

echo MyClass::MYCONST;

1
这个声明是否正确?"const 总是静态的和公共的"? - apil.tamang
8
从 PHP 7.1 开始,类常量可以声明为 private 或 protected。详情请参见 RFC - DisgruntledGoat

13

常量就是一个常数,也就是在声明后其值不能被更改。

静态变量可以在不实例化类的情况下访问,因此它在类的所有实例之间共享。

此外,在函数中还可以有一个静态局部变量,它只被声明一次(在函数的第一次执行时),并且可以在多次函数调用之间保留其值,例如:

function foo()
{
   static $numOfCalls = 0;
   $numOfCalls++;
   print("this function has been executed " . $numOfCalls . " times");
}

10

提到类继承时,你可以使用 selfstatic 关键字来区分不同作用域中的常量或变量。查看以下示例,了解如何访问这些内容:

class Person
{
    static $type = 'person';

    const TYPE = 'person';

    static public function getType(){
        var_dump(self::TYPE);
        var_dump(static::TYPE);

        var_dump(self::$type);
        var_dump(static::$type);
    }
}

class Pirate extends Person
{
    static $type = 'pirate';

    const TYPE = 'pirate';
}

然后执行:

$pirate = new Pirate();
$pirate::getType();

或:
Pirate::getType();

输出:

string(6) "person" 
string(6) "pirate" 
string(6) "person" 
string(6) "pirate"

换句话说,self::指的是在其被调用的同一作用域中静态属性和常量(在本例中为Person超类) ,而static::将在运行时从作用域访问该属性和常量(因此在这种情况下是在Pirate子类中)。
在php.net上了解更多关于延迟静态绑定的内容,请单击此处。 还可以在另一个问题的答案中这里这里查看。

4

将类方法或属性声明为静态,可以在不需要实例化该类的情况下访问它们。

类常量就像普通常量一样,无法在运行时更改。这也是您唯一使用const的原因。

私有、公共和受保护是描述谁可以访问哪个参数/方法的访问修饰符。

公共意味着所有其他对象都可以访问。 私有意味着只有实例化的类可以访问。 受保护意味着实例化的类和派生类可以访问。


2

总结一下@Matt的好回答:

  • 如果你需要的属性不应该被改变,那么常量是正确的选择

  • 如果你需要的属性可以被改变,使用静态

例如:

class User{
    private static $PASSWORD_SALT = "ASD!@~#asd1";
    ...
}

class Product{
    const INTEREST = 0.10;
    ...
}

编辑:需要注意的是,PHP 7.1.0引入了指定类常量可见性的支持


2

这是我关于静态成员、常量变量和访问修饰符(private、public 和 protected)所学到的知识。

常量

定义

顾名思义,常量变量的值不能被改变。与普通变量不同的是,在声明或使用常量变量时不使用 $ 符号。

该值必须是一个常量表达式,不能是变量、属性、数学运算的结果或函数调用的结果。

注意:变量的值不能是关键字(例如 self、parent 和 static)。

在 PHP 中声明常量:

<?php
class constantExample{

   const CONSTANT = 'constant value'; //constant

 }
?>

常量的作用域是全局的,可以使用self关键字访问

<?php
class MyClass
{
    const CONSTANT = 'constant value';

    function showConstant() {
        echo  self::CONSTANT . "\n";
    }
}

echo MyClass::CONSTANT . "\n";

$classname = "MyClass";
echo $classname::CONSTANT . "\n"; // As of PHP 5.3.0

$class = new MyClass();
$class->showConstant();

echo $class::CONSTANT."\n"; // As of PHP 5.3.0

?>

静态

定义

静态关键字可以用于声明类、成员函数或变量。在类中声明为静态的成员是全局的,也可以使用 self 关键字访问。将类属性或方法声明为静态使它们可以在不需要实例化类的情况下访问。声明为静态的属性不能通过实例化的类对象访问(虽然静态方法可以)。如果没有使用可见性声明(public、private、protected),则该属性或方法将被视为公共属性或方法。因为静态方法可以在未创建对象实例的情况下调用。

注意:在声明为静态的方法内部,伪变量 $this 不可用。静态属性不能通过对象使用箭头运算符 -> 访问。

从 PHP 5.3.0 开始,可以使用变量引用类。该变量的值不能是关键字(例如 self、parent 和 static)。

静态属性示例

<?php
class Foo
{
    public static $my_static = 'foo'; //static variable 

    public static function staticValue() { //static function example
        return self::$my_static;  //return the static variable declared globally
    }
}

?>

访问静态属性和函数示例

 <?php
     print Foo::$my_static . "\n";

    $foo = new Foo();
    print $foo->staticValue() . "\n";
    print $foo->my_static . "\n";      // Undefined "Property" my_static 

    print $foo::$my_static . "\n";
    $classname = 'Foo';
    print $classname::$my_static . "\n"; // As of PHP 5.3.0

    print Bar::$my_static . "\n";
    $bar = new Bar();
    print $bar->fooStatic() . "\n";

 ?>

公有、私有、受保护的(也称为访问修饰符)

在阅读下面的定义之前,请先阅读本文关于封装的文章。这将帮助您更深入地理解这一概念。

维基百科的链接1

教程点关于封装的链接

定义

使用private、public、protected关键字可以控制类中成员的访问权限。声明为公有的类成员可以在任何地方访问。声明为受保护的类成员只能在类本身和继承和父类中访问。声明为私有的成员只能被定义成员的类访问。

示例

 <?php 
class Example{
 public $variable = 'value'; // variable declared as public 
 protected $variable = 'value' //variable declared as protected
 private $variable = 'value'  //variable declared as private

 public function functionName() {  //public function
 //statements
 }

 protected function functionName() {  //protected function
 //statements
 }
  private function functionName() {  //private function
   //statements
   }

} 
 ?> 

访问公共、私有和受保护成员的示例

公共变量可以从类内外进行访问和修改。但是,只能从类内部访问和修改私有和受保护的变量和函数,不能在类外部修改受保护或公共成员的值。

  <?php 
  class Example{
    public $pbVariable = 'value'; 
    protected $protVariable = 'value'; 
    private $privVariable = 'value';
    public function publicFun(){

     echo $this->$pbVariable;  //public variable 
     echo $this->$protVariable;  //protected variable
     echo $this->privVariable; //private variable
    }

   private function PrivateFun(){

 //some statements
  }
  protected function ProtectedFun(){

 //some statements
  }

  }


 $inst = new Example();
 $inst->pbVariable = 'AnotherVariable'; //public variable modifed from outside
 echo $inst->pbVariable;   //print the value of the public variable

 $inst->protVariable = 'var'; //you can't do this with protected variable
 echo $inst->privVariable; // This statement won't work , because variable is limited to private

 $inst->publicFun(); // this will print the values inside the function, Because the function is declared as a public function

 $inst->PrivateFun();   //this one won't work (private)
 $inst->ProtectedFun();  //this one won't work as well (protected)

  ?>

想要了解更多信息,请阅读关于可见性的PHP文档:Visibility Php Doc

参考资料:php.net

希望您已经理解了这个概念。感谢您的阅读 :) :) 祝您一切顺利


0
我希望你专注于一个使用self::static::不同的案例,这也有助于调试时的注意事项。
<?php
    class ClassTwo extends ClassName {
       const MY_CONST = 3;
    }
    class ClassName {
        const MY_CONST = 5;
        static function check():int { 
            return static::MY_CONST;  // static:: using last lvl parental MY_CONST
        }
        static function check2():int { 
            return self::MY_CONST;  // self:: exactly this class MY_CONST
        }
    }
    echo ClassTwo::MY_CONST;  // returns 3
    echo ClassTwo::check();  // returns 3
    echo ClassTwo::check2();  // returns 5

?>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接