开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第一阶段:静态成员】学习笔记,与课程紧密联系,让用户快速学习知识。
课程地址:https://developer.aliyun.com/learning/course/711/detail/12667
静态成员
内容介绍:
一、概念
二、步骤
三、示例
四、小结
范围解析操作符是用来实现类直接访问类成员的,类成员里面有类常量,还有静态成员。这节的目标是理解静态成员的概念,掌握静态成员的性质以及访问方式,能够利用静态实现一些高级的或者高速的、高效的访问操作。
一、概念
静态成员:使用 static 关键字修饰的类成员,类成员前面不再仅仅局限于访问修饰限定符,表示使用 static 修饰的该成员属于类访问,它是用类来访问的,不是用对象来访问的。
1. PHP 静态成员有两种:静态属性、静态方法。
属性和方法前面加了 static 关键字就应该变成类的东西而不是对象的东西。
2.静态成员是明确用来给类访问的,而不是对象。
3.静态成员只是多了一个 static 关键字修饰。
本身也可以被对象访问,属性和方法只加了一个 static 关键字,表示应该由类来访问,而对象也可以尝试去访问。
4.静态成员使用不同访问修饰限定符限定,效果一致。
二、步骤
定义类结构,确定一些成员(属性、方法),如果确定不需要对象访问,直接通过类访问,使用 static 关键字修饰,让它变成静态成员,静态成员最后直接用类进行访问。
三、示例
1、静态属性:在类中定义属性的时候使用 static 关键字修饰,比如 public 就是一个普通的属性,但是 public static $count 就是一个静态属性。
class saler{
#属性
public Smoney = 0;
public static $count = 0; #静态属性
}
这就相当于定义了一个类,有普通属性、静态属性。
<?php
#静态成员
class Saler{
#属性
public $money = 0;
public static $count = 0; #静态属性
}
首先,定义了类结构,普通的属性和用 static 关键字修饰的属性,想要访问静态属性可以直接使用类名+范围解析操作符+属性名,注意此时它是带$符号的,因为前面没有$符号。
#静态方法
echo Saler:: $count;
确实访问了,没有报错。受益于范围解析操作符,类直接访问,此时是没有对象的,意味着内存空间不需要额外的支出对象成本,所以效率自然要高。
2、静态方法:在类中定义方法的时候使用 static 关键字修饰,访问的时候使用类+范围解析操作符+静态方法名字()访问
定义一个方法叫做 static 的方法 showClass,里面的内容只是输出这个类名:
#方法
public static function showClass(){
echo __CLASS__;
}
这样就有了一个方法,但是这个方法是静态方法,为了做对比,再做一个普通的方法:
public function showCount(){
echo __METHOD__;
}
这个普通方法只是做一组对比,然后访问静态属性、静态方法,
#静态属性
echo Saler::$count;
#静态方法
Saler::showClass();
能够访问,再次证明有了静态的东西,类就可以直接访问。
3、在类的内部也可以访问静态成员,同样是使用类名+范围解析操作符+静态属性/静态方法()
比如要在 showClass 方法里增加访问静态属性,
echo Saler:: $count;
会发现里面又输出了一次0,第一个0是属性静态访问输出的,第二个都在这里面,所以这是可以访问的,类的内部也可以用类名来实现类成员的访问。
4、静态方法本质也是类中定义的方法,它跟普通的方法是存在一块的,所以对象如果想访问也可以进行访问的,但是不建议
#实例化
$s = new Saler();
拿到类的对象后通过对象来访问,
echo $s -> money;
刷新,没问题。但是
echo $s-> count;
#对象不能访问静态属性
没有这样的属性,因为这是静态属性,但是用了非静态,用对象来访问,对象可以理解为动态,因为必须要动态的实例化一个对象,所以动态访问是不行的。
只要加了->,系统就认为是要访问普通的,就是对象来访问。
假设要访问方法,
$s->showClass();
#输出0
能访问,印证了静态方法、普通方法都是存在类里面,对象要访问只要找到类,找到同名的东西就可以去访问
印证了静态的方法或者普通的方法都存在类里,对象要访问只要找到类、同名的东西就可以访问。
echo $s::$count;
#可以访问,但不建议
可以访问,因为拿到对象后它会找到对象所属的类,然后替换类名。
5、同理,方法也是在类内部,刚刚操作了所有后,会发现忽略了方法 showCount,那对象自然可以访问了,
$s -> showCount();
可以访问。
要说明因为方法在内部,编译时就存在,因此可以通过类来进行访问,使用范围解析操作符,但是非常不建议,就是禁止(会报错:因为系统认为类来访问的东西就是静态的东西)
#类访问普通方法
Saler::showCount();
确实也输出了,不要看前面的报错,但是它告诉我们报错了,这不是一个静态方法 showCount,所有就不应该用静态的方式来访问,范围解析操作符属于静态方式,不应该用类直接来访问。
6、如果想用别的东西,比如在方法里用 $this,此时它不能放在里面,静态方法里面不能放$this。
public static function testThis(){
var_ dump($this);
#静态方法中不能使用$this
}
}
编译时没问题。
Saler::testThis();
虽然编译未报错,但此时有一个致命错误,因为 this 不在对象上下文,说明这个上下文是类的上下文,它是给静态的,静态是给类访问的,所以这里不能用$this。
类能够访问静态的,正常,但是类又能够访问普通的方法,这就矛盾,而对象可以访问普通的属性和方法,还可以访问静态方法,还可以使用范围解析操作符访问对应的静态属性,该如何操作?记住类常量静态的属性或者方法是给类访问的,应该由类来访问,而普通的属性和方法应该由对象访问。它们彼此之间有一些交叉,涉及到它们深入的一些交互的问题,比如类与对象是有关系的,彼此可以穿插,但是不会这么去用。
四、小结
1.为了保障类能直接访问数据和操作数据,可以在属性和方法前增加 static 关键字变成静态属性和静态方法,证明是专属于类的,就可以用类来访问,这样类的权限和功能变大,有可能不需要依赖对象就可以做东西,可以定义变量来保存数据,定义方法来操纵数据,只要 static 就行。类的东西既然存在类里,那么它就是固定的,不可能做到每个对象都有不同的数据,是有局限的。
2.类通过类名+范围解析操作符+静态成员的方式进行访问,还包括类常量。
3.静态成员也受访问修饰限定符的限定,要确定是在类外面还是在类内部进行访问。
4.对象本质可以无条件访问静态方法,因为方法本身放在一起,所以可以访问,访问里面没有任何不妥,不会产生任何不存在的问题,而类只能访问不带$this 的普通方法(不建议),$this 叫内部对象,对象是别人来访问时指向外部的对象,而类访问时类是可以脱离对象存在的,没有对象时,类也可以直接访问。
5.静态成员是给类访问的,非静态成员是给对象访问的。
(1)静态属性和方法(静态和非静态)都是保存在类结构中(代码段);
(2)普通属性保存在对象生成的对象空间里(堆),而静态属性存在类的空间里,有多少对象就会有多少普通属性,它们之间是彼此无关的,但是不管进行多少静态属性的访问,它都只有一个,类是唯一的。
6.静态成员的访问效率比非静态成员高,因此有种说法是能用静态的时候就不用非静态,尽可能多的使用静态,因为此时没有对象的开销,它能够让内存效率更高。注意对象的特点是多元化,而类的特点也就是静态是单一化,如果做的事情是单一的,尽可能静态,如果做的事情发现不同的对象就不同,那么只能用非静态。










