思考:类的内部的静态方法内可能会访问其他静态成员或者类常量,这个时候必须每次使用类名::那么如果类名修改的画岂不是很麻烦?
引入:静态成员或者类常量的访问时必须使用类名进行访问的,不过为了方便类名的更新,减少开发者维护成本,系统引入一个类似$this代表对象的方案,self关键字来代表当前类
self关键字(自己 本身的意思)
定义:self关键字是一种在类的内部(方法里面)使用,代替类名的写法,能够保障用户方便修改类名字。
1.self是用来代替类名的,与范围解析操作符::一起使用
<?php class fly{ private static $count=0; static function show(){ echo fly::$count; //使用类名::静态成员访问 echo self::$count; //使用关键字self::静态成员访问 } } fly::show(); //访问静态方法 返回 00 self关键字只能在类中使用 ?>
2.self也可以在类的内部方便实例化对象,比如构造方法被私有化之后,就没有办法在类外部实例化对象,此时可以在类内部进行对象实例化
<?php class fly{ private function __construct(){ //构造函数被私有化 此类不能被实例化 } } new fly(); //报错 ?>
<?php class fly{ private function __construct(){ //构造函数被私有化 此类不能被实例化 } static function instance(){ return new self(); } } // new fly(); //报错 $a=fly::instance(); var_dump($a); //返回的是fly的对象 // 自己 只有类常量或者静态成员才能使用::范围解析操作符 ?>
总结
1.self是一种在类内部用来代替类名的关键字
2.self可以用来在类内部访问静态成员(类常量也可以)
3.self也可以在类内部用来实例化对象
类的加载【重要】
思考:类不管是直接访问静态成员还是先实例化然后访问类成员,都有一个前提:类必须在内存中存在,那是不是以为这所有类操作前,都必须先确认类在内存中是否存在呢?
引入:类的任何操作都需要确认类在内存存在的,不过累文件通常是一个类单独形成一个文件的,所以在操作之前需要进行类的加载
定义:所谓类的加载,本质是因为类的访问必须保证类在内存中已经存在,所以需要在用类之前将类所在的php文件加载到内存
1.手动加载:即访问某个文件之前,使用包含将类所在的文件加载进来
<?php //类文件 class info{ } ?>
<?php include_once 'class_load.php'; //引用文件class_load.php $a=new info(); var_dump($a); ?>
2.加载类文件是一种比较消耗资源的方式,所以有的时候不确认类事都在内存中存在,可以事先使用class_exists()函数来判定是否存在,存在就不用加载,不存在才加载
<?php if(!class_exists('class_load')){ //类不存在 echo '类加载'; include_once 'class_load.php'; } $a=new info(); var_dump($a); ?>
3.自动加载:php没有那么只能得系统自动加载,所谓自动加载只是php提供了一种加载机制:即实现定义一个函数__autoload(),然后当系统需要使用类,而内存中有不存在的时候,系统就会自动调用__autoload()函数来加载类文件
<?php //类文件 //规定:要想实现自动加载,必须类名和文件名要相同 class info{ } ?>
<?php //自动加载 function __autoload($classname){ //输出参数 echo $classname; include_once $classname.'.php'; } $a=new info(); var_dump($a); ?>
4.一个系统里,可能类文件会放到不同的路径下,因此一个完整的自动加载函数,应该要进行文件判定以及加载功能。
<?php //自动加载 function __autoload($classname){ //假设当前文件目录下有c和m文件夹,里面有类文件 //先尝试去c文件夹去找 $c_file='c/'.$classname.'php'; if(file_exists($c_file)){ include_once $c_file; exit; }else{ //尝试m文件夹找 $m_file='m/'.$classname.'php'; if(file_exists($m_file)){ include_once $m_file; exit; } } } $a=new info(); var_dump($a); ?>
注意:自动加载是指按照开发者规定的路径去寻找对应的文件,并实现包含,如果文件不存在,那么系统会在使用类的时候报错,因为这是开发者自己犯的错,系统不能规范
5.随着php版本的提升,在7以后,不怎么建议直接使用__autoload()函数,而是采用一种注册机制,将用户自定义的函数,放到系统内部,使用spl_autoload_register(定义好的函数)。
本质与__autpload()一样。
<?php //自定义函数,用来加载类文件,也需要一个参数来接收要加载的类名字 function my_autoload($val){ //功能与autoload()一样 $c_file='c/'.$val.'php'; if(file_exists($c_file)){ include_once $c_file; }else{ //说明c盘符没有对应的文件 $m_file='m/'.$m_file.'php'; include_once $m_file; } } //此时,上述函数永远不会自动执行,除非将函数注册到系统内部 spl_autoload_register('my_autoload'); $a=new info(); var_dump($a); ?>
注意:该方式其实本质就是通过两步完成了__autoload()一步操作,但是spl_autoload_register()函数可以注册多个自定义的加载函数,更方便管理
总结:
类的使用必须先保证内存中该类存在
可以使用手动加载来确保类的使用安全,优点是明确,缺点是繁琐(类文件名可以随意没有规范)
可以使用自动加载来让系统按照开发者设定的路径和方式去寻找类,并尝试加载到内存,(尽量让类文件名字统一,保证类名和文件名有关联)
自动加载可以使用__autoload()函数来实现,也可以使用自定义函数+spl_autoload_register()注册共同实现(推荐使用这个)
基本上所有的框架都在使用自动加载机制