面向对象知识点续及单例模式
1、命名空间
命名空间的作用是避免了项目越来越大出现的命名冲突和混乱的问题
命名空间一般与文件的目录相对应,第一个命名空间前面不能有任何代码
在不同空间之间不可以直接调用其它元素,需要使用命名空间的语法:
<?php namespace Article; class Comment { } namespace MessageBoard; class Comment { } //调用当前空间(MessageBoard)的Comment类 $comment = new Comment(); //调用Article空间的Comment类 $article_comment = new \Article\Comment(); ?>
可以看到,在MessageBoard空间中调用article空间里的Comment类时,使用了一种像文件路径的语法: \空间名\元素名,除了类之外,对函数和常量的用法是一样的
2、自动加载
最早的php项目都是通过手工include或者require来载入依赖的文件的,当项目变大时,一个文件要依赖很多个php类,就需要写几十行require或者include语句,这会导致管理很不方便,也会导致一些错误。比如某个类删除了,但是require这个文件的语句没有去掉,会报一个致命错误。这时候可以采用类自动载入的方式处理这种类依赖关系。
<?php spl_autoload_register(function ($class_name) { require_once $class_name . '.php'; }); $obj = new MyClass1(); $obj2 = new MyClass2(); ?>
之前用的是__autoload() 函数,已经被废弃
3、链式查询
现在大多数框架都支持链式查询,其原理很简单:每个链式操作方法最后都返回当前对象
以下是示例文件:
//database.php function where($where) { return $this; } function order($order) { return $this; } function limit($limit) { return $this; }
这样便可持续调用了下一个方法了。
$db=new IMooc\Database(); $db->where("id>20")->order('create_time desc')->limit(10);
4、魔术方法
4.1、__get、__set方法,将对象的属性进行接管
一般来说,总是把类的属性定义为private,这更符合现实的逻辑
但是在类外调用一个未定义或者私有的属性会报错,便可以通过__get、__set方法获取和赋值其属性
$object=new IMooc\Object();
$object->name='zhangsan';
echo $object->name;
<?php namespace IMooc; class Object { private $name='lisi'; function __set($key, $value) { $this->$key = $value; } function __get($key) { return $this->$key; } }
4.2、__call、__callStatic ,控制类的方法
方法不存在时自动调用,可在报错时使用,保证代码的健壮性
5、单例模式
有些类只需要实例化一次,像数据库连接类,实例化多次的话会浪费资源,这时候就会用到单例模式
简单的来说是“三私一公”:
构造方法私有化后就不能从外部实例化类了,但是怎么实例化呢?
就要用到静态方法了,将其公有化,便可在外部实例化类了,
在方法里判断对象是否为空,如果为空就实例化,存在就直接将它返回,这样便实现了只实例化一次了
<?php namespace IMooc; class Database { //私有化内部实例化的对象 private static $instance = null; //私有化构造方法,禁止外部实例化 private function __construct(){} //私有化__clone,防止被克隆 private function __clone(){} // 公有静态实例方法 public static function getInstance(){ if(!empty(self::$instance)){ return self::$instance; }else{ self::$instance=new Database(); return self::$instance; } } } $obj1=Database::getInstance(); $obj2=Database::getInstance(); $obj3=Database::getInstance(); var_dump($obj1,$obj2,$obj3); echo $obj1==$obj2?1:0; echo "<br>"; echo $obj1==$obj3?1:0;
打印结果如下: