php面向对象之self关键字 、类的加载

思考:类的内部的静态方法内可能会访问其他静态成员或者类常量,这个时候必须每次使用类名::那么如果类名修改的画岂不是很麻烦?  

引入:静态成员或者类常量的访问时必须使用类名进行访问的,不过为了方便类名的更新,减少开发者维护成本,系统引入一个类似$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()注册共同实现(推荐使用这个)

  基本上所有的框架都在使用自动加载机制