PHP基础加强系列六之OOP相关内容(一...

胡三金 2017-06-20 16:21:57 1048 0 comments

序言:本篇文章主要讲了PHP面向对象编程相关的知识,有点乱;

(1).类的自动加载

当要加载的类文件很多的时候可以使用;

例如一个初始化文件要引入很多类文件

现在有一个init.php要引入Dog.class.php,Cat.class.php,Pig.class.php.................

一般的情况是通过require来引入,像下面这样:

require './Dog.class.php';
require './Cat.class.php';
require './Pig.class.php';
.....

这样的坏处是不利于维护,如果引入的某些类文件并没有使用,就会造成浪费,所以现在引入__autoload

function __autoload($class_name){
    require './'.$class_name.'.class.php';
}

只用一行代码就能实现类文件按需加载,前提是类文件和初始文件在同一个文件夹下,这样不利于扩展,如果我有另外的类文件放在不同的目录下,这个时候再这样写就不好了;所以可以通过建立数组映射,或者遍历文件目录来获取类文件,下面简单写个数组映射;

$class_map = [
    'Dog' => './upload/Dog.class.php',
    'Cat' => './xx/Cat.class.php'
];
function __autoload($class_name){
    global $class_map;
    require $class_map[$class_name];
}

Dog类存在于当前目录下的upload目录中,Cat类位于xx目录下,这样通过数组映射,就能实现对类文件的加载;当然使用遍历目录的方式可以更方便;还有一种更高级的类的自动加载,使用spl_autoload_register,通过回调的方式,来自动加载;

$class_map = [
    'Dog' => './upload/Dog.class.php',
    'Cat' => './xx/Cat.class.php'
];
function MyAutoload($class_name){
    global $class_map;
    require $class_map[$class_name];
}
spl_autoload_register('MyAutoload');
$dog = new Dog();
echo $dog->talk();
$cat = new Cat();
echo $cat->talk();

这样输出也可以,通过spl_autoload_register,我们可以自定义函数来自动加载类文件;

(2).面向对象之静态变量

当有一个需求:例如有一个游戏,要求每加入一个人就记录一下,最后返回加入游戏的人数;如果不是oop很简单,但是如果是oop呢,同样简单;

这个时候就需要用到静态变量来记录人数;如果不声明静态变量,各个对象之间就不能共享这个游戏人数;举例子说明

class Game{
    public $name = '';
    public $child_count = 0;
    public function __construct($name)
    {
        $this->name = $name;
    }
    public function joinGame()
    {
        echo $this->name.'加入游戏';
        $this->child_count += 1;
    }
    public function personCount()
    {
        return '总计'.$this->child_count.'人加入游戏';
    }
}
$p1 = new Game('张飞');
$p2 = new Game('关羽');
$p1->joinGame();
$p2->joinGame();
echo $p1->personCount();
echo $p2->personCount();

使用这种普通变量来计数,每个对象的计数都是单独的;

输出:

张飞加入游戏

关羽加入游戏

总计1人加入游戏

总计1人加入游戏

现在做一下修改,将普通变量声明为静态:

class Game{
    public $name = '';
    public static $child_count = 0;
    public function __construct($name)
    {
        $this->name = $name;
    }
    public function joinGame()
    {
        echo $this->name.'加入游戏';
        self::$child_count++;
    }
    public function personCount()
    {
        return '总计'.self::$child_count.'人加入游戏';
    }
}

输出:

张飞加入游戏

关羽加入游戏

总计2人加入游戏

总计2人加入游戏

因为在内存中的数据区静态变量和普通变量不一样,它会单独存在一个区域,而所有对象都指向这个静态数据区,如果是普通变量,同样一个数据区会存在两个普通变量,所以不一样;

注意细节:类中使用了关键字self,而不是$this,因为$this属于对象范畴,self属于类范畴,::表示范围解析符,->是对象运算符;类中public静态变量,在类外不用实例化就能调用,因为它属于类范畴,所以你可以这样用

class Dog{
  public static $name = '小黑';
}
echo Dog::$name;

输出:小黑,这里并没有实例化类Dog,但是可以通过类名::变量名来访问静态变量,即使你里面有构造函数,也一样

class Dog{
    public static $name = '小黑';
    function __construct()
    {
        echo '哈哈';
    }
}
echo Dog::$name;

输出:小黑,因为构造函数是在实例化对象的时候才会触发;

如果你new了一个对象,就会触发

class Dog{
    public static $name = '小黑';
    function __construct()
    {
        echo '哈哈';
    }
}
echo Dog::$name;
$dog = new Dog();

输出:小黑哈哈  

同理的还有静态方法,但是有一点需要注意就是静态方法中不能访问不同变量属性,这样会报错,因为静态方法是类相关,是抽象的,而普通变量是具体的,与对象相关,但是普通方法可以访问静态方法。


(3).PHP单利模式

在一次http请求中只能有一个对象实例,单例模式确保某个类只有一个实例,而且自行实例化并向整个系统提供这个实例。

final class Girl{
    public $name;
    private static $instance = null;
    private function __construct($name)
    {
            $this->name = $name;
    }
    public static function getSingle($name){
	//使用类型运算符判断是不是类本身
        if(!(self::$instance instanceof self))
        {
            self::$instance = new self($name);
        }
        return self::$instance;
    }
    private function __clone()
    {

    }
}
girl = Girl::getSingle('小白'); girl2 = Girl::getSingle(‘小红’);
echo girl->name; echo girl2->name;
var_dump(girl2,girl2,girl);

输出:

小白小白
F:\wamp64\www\test\test.php:1179:
object(Girl)[1]
  public ‘name’ => string ‘小白’ (length=6)
F:\wamp64\www\test\test.php:1179:
object(Girl)[1]
  public ‘name’ => string ‘小白’ (length=6)

//解释:构造函数和魔术方法__clone都变成私有的,私有构造函数是为了防止类外new一个对象,私有__clone是为了防止类外clone一个对象;final关键字是为了防止类被继承;


(4).对象运算符(->)的连用

例如:echo student->getSchool()->getClass()->name;

小例子:

class Student{
    public name;
    private school;     function __construct(name)
    {
        this->name = name;
    }
    public function setSchool(value)     {         this->school = $value;
    }

    public function getSchool()
    {
        return $this->school;
    }
}

class School{
    public name;     private school_class;
    function __construct(name)     {         this->name = name;     }     public function setClass(value)
    {
        this->school_class = value;
    }

    public function getClass()
    {
        return $this->school_class;
    }
}

class SchoolClass{
    public name;     private class_number;
    function __construct(name)     {         this->name = $name;
    }

    public function setNumber(value)     {         this->class_number = $value;
    }

    public function getNumber()
    {
        return $this->class_number;
    }
}

class = new SchoolClass('网工二班'); class->setNumber(120);
school = new School('成都东软学院'); school->setClass(class);class); student = new Student('王二狗');
student->setSchool(school);

echo student->getSchool()->getClass()->name;

输出:网工二班

//解释:有三个类,学生,学校,班级,通过学生能访问到学校和班级的信息;通过一个类能访问到其它类的信息就需要对象运算符;

另外的例子:通过一条狗找到狗主人,通过狗主人找到狗

class Dog{
    public name;
    private $master;

    function __construct(name)     {         this->name = $name;
    }

    public function setMaster(value)     {         this->master = $value;
    }

    public function getMaster()
    {
        return this->master;     } } class Master{     public name;
    private dog;     function __construct(name)
    {
        this->name = name;
    }
    public function setDog(value)     {         this->dog = value;     }     public function getDog()     {         return this->dog;
    }
}

dog = new Dog('小黑'); master = new Master('王二狗');
dog->setMaster(master);
master->setDog(dog);

echo ‘王二狗的宠物狗的名字:’.master->getDog()->name.''; echo '宠物狗小黑的主人:'.dog->getMaster()->name;

输出:

王二狗的宠物狗的名字:小黑

宠物狗小黑的主人:王二狗


转载请注明出处,谢谢!






标签
PHP
评论一下

评论列表

暂时没有评论,快来评论吧..