本教程操作环境:windows7系统、php8.1版、dell g3电脑。
php static静态详解
php 类属性和方法都需要在类实例化后才能调用(常量属性除外),但是,php 还提供了静态属性和静态方法,所谓「静态」指的是无需对类进行实例化,就可以直接调用这些属性和方法。静态类不是不可以实例化,而是不需要实例化就可以用。
静态成员的定义用static关键字来修饰类的属性、方法,称这些属性、方法为静态属性、静态方法。
1、静态属性语法:
static 属性名
实例:
<?phpclass foo { public static $my_static = 'hello'; }?>
2、静态方法语法:
static function 方法名{ //代码}
实例:
<?phpclass foo { public static function staticvalue() { return 'hello'; }}?>
注:静态属性和方法与对象属性和方法一样,支持设置 private、protected、public 三种可见性级别。
静态成员的调用1、在类外调用静态属性/方法通过 类名::属性/方法 的方式调用。
<?phpclass mystatic { public static $staticvalue = 'zhangsan'; public static function staticmethod() { $a = 'hello'; return $a; }}echo '$staticvalue: '.mystatic::$staticvalue.php_eol;echo '$a: '.mystatic::staticmethod().php_eol;?>
注:预定义常量 php_eol 表示系统换行符。
结果:
$staticvalue: zhangsan$a: hello
通过 对象名::属性/方法 的方式调用。
<?phpclass mystatic { public static $staticvalue = 'zhangsan'; public static function staticmethod() { $a = 'hello'; return $a; }}$obj = new mystatic();echo '$staticvalue: '.$obj::$staticvalue.php_eol;echo '$a: '.$obj::staticmethod();?>
结果:
$staticvalue: zhangsan$a: hello
通过对象名 -> 方法调用、对象名 -> 属性会失败。
<?phperror_reporting(0);class mystatic { public static $staticvalue = 'zhangsan'; public static function staticmethod() { $a = 'hello'; return $a; }}$obj = new mystatic();echo '$staticvalue: '.$obj -> staticvalue.php_eol;echo '$a: '.$obj -> staticmethod();?>
结果:
$staticvalue:$a: hello
2、在非静态方法中调用静态属性/方法通过 self::属性/方法 的方式调用,self 指向当前类,就像 $this 指向当前对象一样;而在没有实例化的情况下,$this 指针指向的是空对象,所以不能动过它引用静态属性和方法。
<?phpclass mystatic { public static $staticvalue = 'zhangsan'; public static function staticmethod() { $a = 'hello'; return $a; } public function nostatic(){ echo '$staticvalue: '.self::$staticvalue.php_eol; echo '$a: '.self::staticmethod(); }}$obj = new mystatic();$obj -> nostatic();?>
结果:
$staticvalue: zhangsan$a: hello
3、在静态方法中调用静态属性/方法与在非静态方法中调用静态属性/方法一样。
<?phpclass mystatic { public static $staticvalue = 'zhangsan'; public static function staticmethod1() { $a = 'hello'; return $a; } public static function staticmethod2(){ echo '$staticvalue: '.self::$staticvalue.php_eol; echo '$a: '.self::staticmethod1().php_eol; }}mystatic::staticmethod2();$obj = new mystatic();$obj -> staticmethod2();?>
结果:
$staticvalue: zhangsan$a: hello$staticvalue: zhangsan$a: hello
4、调用另一个类的静态属性/方法如果在一个类中调用其他类的静态属性和方法,需要通过 完整类名:: 进行引用。
<?phpclass mystatic1 { public static $staticvalue1 = 'xiaomin';}class mystatic2 { public static $staticvalue2 = 'zhangsan'; public static function staticmethod() { echo '$staticvalue1: '.mystatic1::$staticvalue1.php_eol; echo '$staticvalue2: '.self::$staticvalue2.php_eol; }}mystatic2::staticmethod();$obj = new mystatic2();$obj -> staticmethod();?>
结果:
$staticvalue1: xiaomin$staticvalue2: zhangsan$staticvalue1: xiaomin$staticvalue2: zhangsan
5、调用private、protected可见性级别的静态属性/方法由于private、protected属性的限制只在类内调用,想在类外调用,需为外部提供一个public的方法,方法访问private、protected属性。术语:类对外提供接口。
<?phpclass mystatic { public static $staticvalue1 = 'zhangsan'; private static $staticvalue2 = 20; protected static $staticvalue3 = 'student'; private static function staticmethod() { $a = 'hello'; return $a; } public function port1() { echo '$staticvalue1: '.self::$staticvalue1.php_eol; echo '$staticvalue2: '.self::$staticvalue2.php_eol; echo '$staticvalue3: '.self::$staticvalue3.php_eol; echo '$a: '.self::staticmethod().php_eol; } public static function port2() { echo '$staticvalue1: '.self::$staticvalue1.php_eol; echo '$staticvalue2: '.self::$staticvalue2.php_eol; echo '$staticvalue3: '.self::$staticvalue3.php_eol; echo '$a: '.self::staticmethod().php_eol; }}$obj = new mystatic();$obj -> port1();echo \r\n;mystatic::port2();?>
结果:
$staticvalue1: zhangsan$staticvalue2: 20$staticvalue3: student$a: hello$staticvalue1: zhangsan$staticvalue2: 20$staticvalue3: student$a: hello
静态属性支持动态修改在实际应用中会有一个类的多个对象,可能会共享一份数据。类常量和静态属性都可以实现。静态属性与类常量相似(相同),唯一的区分是类常量不可以更改,静态属性可以更改。访问方法是一样的,都可以使用::访问。 静态属性需要加$,常量名前没有$,所以访问类常量时根本不需要加。
1、类常量<?phpclass myconst { const a = 1234;}$obj1 = new myconst();echo 'a: '.$obj1::a.php_eol;$obj1->a='aaa';//$obj1::a='aaa';会报错echo \r\n;$obj2 = new myconst();echo 'a: '.$obj2::a.php_eol;?>
结果:
a: 1234a: 1234
2、静态属性<?phpclass mystatic { public static $a = 1234;}echo '$a: '.mystatic::$a.php_eol;mystatic::$a = 6666;echo '$a: '.mystatic::$a.php_eol;$obj1 = new mystatic();echo '$a: '.$obj1::$a.php_eol;mystatic::$a = 5555;$obj2 = new mystatic();echo '$a: '.$obj2::$a.php_eol;echo '$a: '.$obj1::$a.php_eol;?>
结果:
$a: 1234$a: 6666$a: 6666$a: 5555$a: 5555
静态成员的继承和重写和非静态属性/方法一样,静态属性和方法也可以被子类继承,静态属性和方法还可以被子类重写。
1、静态属性子类可以重写父类的静态成员变量, 但父类的静态变量依然存在, 这两个静态成员变量是独立的. 会根据调用的类名分别进行访问。
<?phpclass mystatic{ static public $a; //定义一个静态变量 static function test() //定义静态方法来操作并输出静态变量 { self::$a++; return self::$a; }}class mystatic2 extends mystatic //定义一个子类{ static function test() //定义子类的静态方法 { self::$a++; //访问并操作父类的静态变量 return self::$a; }}$obj1=new mystatic; //新建父类对象echo '此时$a的值为: '.$obj1->test().php_eol; //通过对象调用静态方法test,静态属性$a的值+1$obj2=new mystatic; //新建另一个父类对象echo '此时$a的值为: '.$obj2->test().php_eol; //新父类对象调用静态方法test,静态属性$a的值+1+1$obj3=new mystatic2; //新建子类对象echo '此时$a的值为: '.$obj3->test().php_eol; //子类对象调用同名静态方法test, 静态属性$a的值+1+1+1echo mystatic::$a.php_eol; //通过父类::直接访问静态成员$a变量echo $obj1::$a.php_eol; //通过对象名::可以直接访问静态成员$a变量?>
结果:
此时$a的值为: 1此时$a的值为: 2此时$a的值为: 333
2、静态方法子类可以重写父类的静态方法。
<?phpclass mystatic1 { public static function getclassname() { return __class__; } public static function whoclassname() { echo self::getclassname().php_eol; }}class mystatic2 extends mystatic1{ public static function getclassname() { return __class__; }}echo mystatic1::getclassname().php_eol;echo mystatic2::getclassname().php_eol;?>
通过 __class__ 可以获取当前类的类名,我们分别调用两个类的 getclassname 方法:
结果:
mystatic1mystatic2
说明子类重写了父类的同名静态方法,同样我们在子类上也可以调用父类中的 whoclassname 方法:
<?phpclass mystatic1 { public static function getclassname() { return __class__; } public static function whoclassname() { echo self::getclassname().php_eol; }}class mystatic2 extends mystatic1{ public static function getclassname() { return __class__; }}echo mystatic1::whoclassname();echo mystatic2::whoclassname();?>
结果:
mystatic1mystatic1
为什么第二个打印的结果是父类名 mystatic1 而不是子类名 mystatic2?这是因为, $this 指针始终指向持有它的引用对象,而self 指向的是定义时持有它的类而不是调用时的类,为了解决这个问题,从 php 5.3 开始,新增了一个叫做延迟静态绑定的特性。
延迟静态绑定延迟静态绑定(late static bindings)针对的是静态方法的调用,使用该特性时不再通过 self:: 引用静态方法,而是通过 static::,如果是在定义它的类中调用,则指向当前类,此时和 self 功能一样,如果是在子类或者其他类中调用,则指向调用该方法所在的类。
<?phpclass mystatic1 { public static function getclassname() { return __class__; } public static function whoclassname() { echo static::getclassname().php_eol; }}class mystatic2 extends mystatic1{ //self改为static public static function getclassname() { return __class__; }}echo mystatic1::whoclassname();echo mystatic2::whoclassname();?>
结果:
mystatic1mystatic2
表明后期静态绑定生效,即 static 指向的是调用它的方法所在的类,而不是定义时,所以称之为延迟静态绑定。
此外,还可以通过 static::class 来指向当前调用类的类名,例如我们可以通过它来替代 __class__,这样上述子类就没有必要重写 getclassname 方法了:
<?phpclass mystatic1 { public static function getclassname() { return static::class; } public static function whoclassname() { echo static::getclassname().php_eol; }}class mystatic2 extends mystatic1{}echo mystatic1::getclassname().php_eol;echo mystatic2::getclassname().php_eol;echo mystatic1::whoclassname();echo mystatic2::whoclassname();?>
结果:
mystatic1mystatic2mystatic1mystatic2
同理,self::class 则始终指向的是定义它的类。
静态与非静态的区别静态属性和方法可以直接通过类引用,所以又被称作类属性和类方法。非静态属性和非静态方法需要实例化后通过对象引用,因此被称作对象属性和对象方法。
静态属性保存在类空间,非静态属性保存在对象空间。非静态方法可以访问类中的任何成员(包括静态),静态方法只能访问类中的静态成员。
静态方法可以直接调用,类名调用和对象调用(类名或self::调用),但是非静态方法只能通过对象调用(对象名或$this->调用)。
一个类的所有实例对象,共用类中的静态属性。如果修改了这个类静态属性,那么这个类的所有对象都能访问到这个新值。
静态方法和属性的生命周期跟相应的类一样长,静态方法和静态属性会随着类的定义而被分配和装载入内存中。一直到线程结束,静态属性和方法才会被销毁。 非静态方法和属性的生命周期和类的实例化对象一样长,只有当类实例化了一个对象,非静态方法和属性才会被创建,而当这个对象被销毁时,非静态方法也马上被销毁。静态方法和静态变量创建后始终使用同一块内存,而使用实例的方式会创建多个内存。但静态方法效率上要比实例化高,静态方法的缺点是不自动进行销毁,而实例化的则可以做销毁。
应用场景:静态方法最适合工具类中方法的定义;比如文件操作,日期处理方法等.
静态变量适合全局变量的定义.
推荐学习:《php视频教程》
以上就是php的static静态方法是什么的详细内容。
