本文最后更新于 2024-07-19,文章内容可能已经过时。

OOP入门

OOP

一、概述

oop(object orientied programming ) 面向属性编程。

1、类

具有相同属性和行为的事物

属性:用于表述个体特征的标识

行为:事物所表现出的动作。在类中也叫方法。

2、对象

类的实例化个体。

二、类定义

class 类名{
    访问修饰符 ;  //属性
    访问修饰符 function 方法名(形参列表){     //方法
        方法体;
    }
}

访问修饰符:
属性:
public :  该成员能被外部代码访问和操作
proteted :只允许该类的子类进行访问
private :只允许同一个类内部进行访问  
方法:
public  : 该成员能被外部代码访问和操作
proteted: 只允许该类的子类进行访问  
private :只允许同一个类内部进行访问


class Human{
    public $name="zhang";
    private $age=1;
    public function talk(){
        return "我是".$this->name."--我今年".$this->age."岁了";
    }
    private function run(){
        echo "跑步";
    }
}
$h = new Human;//使用new关键字创建一个Human类的对象
$re = $h->talk();//调用对象的talk方法
echo $re;//打印talk方法返回的结果
$h->run();//这一行会报错,因为
run方法是用private修饰的

三、继承

一个类可以复用另外一个类的属性、方法

至少涉及两个类,父类和子类,使用关键字extends表示继承关系

class Dad{
    public $height=1.8;
    public $eyecolor="blue";
    private $weight=200;
    public function swim(){
        return "我会游泳";
    }
    protected function sing(){
        return "我会唱歌";
    }
    private function speakEnglish(){
        return "我会讲英文";
    }
}
class Son extends Dad{
    //定义一个静态方法
    public static function run(){
        echo '静态方法run';
    }
}
$s = new Son;
echo $s->height;
echo $s->eyecolor;
// echo $son->weight;//这行报错,因为weight是用private修饰的
echo $s->swim();
Son::run();//调用静态方法,只用类名就可以,不需要对象
// echo $son->sing();//这行报错,因为sing是用protected修饰的,只能在子类Son中使用,不能在外部用
// echo $son->speakEnglish();//这行报错,因为speakEnglish是用private修饰的

四、魔术方法

方法 描述
__construct( ) 新对象被创建时候调用
__destruct() 对象被销毁时候调用
__call() 在对象中调用一个不可访问方法时,__call()会被调用。
__callStatic() 在静态上下文中调用一个不可访问方法时,__callStatic() 会被调用。
__get() 读取不可访问(protected 或 private)或不存在的属性的值时会被调用
__set() 在给不可访问(protected 或 private)或不存在的属性赋值时会被调用
__isset() 当对不可访问(protected 或 private)或不存在的属性调用 isset()或 empty() 时,__isset() 会被调用。
__unset() 当对不可访问(protected 或 private)或不存在的属性调用 unset()时,__unset() 会被调用。
__sleep() 执行序列化操作时候先执行这个方法
__wakeup() 执行反序列化操作时候先执行这个方法
__toString() 当一个类被当成字符串使用的时候会调用
__invoke() 当尝试以调用函数的方式调用一个对象时这个方法会调用
__clone() 当复制完成时,如果定义了__clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用,可用于修改属性的值(如果有必要的话)。
class Human{
    public $name="zhang";
    private $age=1;
    public function talk(){
        return "我是".$this->name."--我今年".$this->age."岁了";
    }
    //创建对象时候调用
    public function __construct(){
        echo "__contruct<br>";
    }
    //对象销毁时候调用
    public function __destruct(){
        echo "<br>__destruct";
    }
    //调用不存在的方法时候,会调用这个
    public function __call($name,$args){
        echo "你调用了不存在的方法:".$name."<br>";
    }
    //调用不存在的静态方法时候,会调用这个
    public static function __callstatic ($name,$args){
        echo "你调用了不存在的静态方法:".$name."<br>";
    }
    //读取不存在或者无法访问到的属性时候,会调用这个方法
    public function __get($name){
        echo "读取不存在或者无法访问到的属性:".$name."<br>";
    }
    //设置不存在或者无法访问到的属性时候,会调用这个方法
    public function __set($name,$value){
        echo "设置不存在或者无法访问到的属性:".$name."<br>";
    }
    //当对不可访问(protected 或 private)或不存在的属性调用 isset()或 empty() 时,__isset() 会被调用
    public function __isset($name){
        echo "当对不可访问(protected 或 private)或不存在的属性调用 isset()或 empty() 时,__isset() 会被调用:".$name."<br>";
    }
    //当对不可访问(protected 或 private)或不存在的属性调用 unset()时,__unset() 会被调用。
    public function __unset($name){
        echo "当对不可访问(protected 或 private)或不存在的属性调用 unset()时,__unset() 会被调用:".$name."<br>";
    }
    //当一个类被当成字符串使用的时候会调用
    public function __toString()
    {
        return  "对象要转成字符串__toString方法调用"."<br>";
    }
    //当一个类被当成字符串使用的时候会调用
    public function __invoke($value){
        echo  "当尝试以调用函数的方式调用一个对象时这个__invoke方法会调用"."<br>";
    }
    //当复制完成时,如果定义了\__clone() 方法,则新创建的对象(复制生成的对象)中的 __clone() 方法会被调用
    public function __clone(){
        $this->name="woniu";
        echo "新对象克隆完成:"."<br>";
    }
}
$hu = new Human;//对象初始化
$hu->abc();//调用不存在的方法
Human::staticMethod();//调用不存在的静态方法
echo $hu->xyz;//读取不存在或者无法访问到的属性
$hu->xxx="abc";////设置不存在或者无法访问到的属性
isset($hu->xyz);//对不可访问(protected 或 private)或不存在的属性调用 isset()
unset($hu->xyz);//当对不可访问(protected 或 private)或不存在的属性调用 unset()时,__unset() 会被调用。
echo $hu; //当一个类被当成字符串使用的时候会调用
$hu(1);//当尝试以调用函数的方式调用一个对象时这个方法会调用
$newhu = clone $hu;//克隆新对象
echo $newhu->name;//打印新对象的name属性

五、序列化和反序列化

1、序列化

在页面使用面向对象方式时,传递数据中如果需要使用对象。则需要将对象转化为可以还原的字符串。通常使用序列化对象的方式,将对象转化为序列化字符串。

serialize(对象) ==> 生成了序列化字符串

//定义Human类,并且序列化
class Human{
    public $name="zhang";
    private $age=1;
    protected $score=100;
    //创建对象时候调用
    public function __construct(){
        echo "__contruct<br>";
    }
    //对象销毁时候调用
    public function __destruct(){
        echo "<br>__destruct";
    }
    //对象序列化时候调用
    public function __sleep(){
        return array('name', 'age', 'score');
    }
    //对象反序列化时候调用
    public function __wakeup() {
        echo "<br>__wakeup";
    }
}
$hu = new Human;
echo serialize($hu);//这个是不使用编码输出的序列化结果
echo "<hr>";
echo urlencode(serialize($hu));//这个是使用编码输出的序列化结果
以上要注意序列化时候自动 调用了魔术方法__sleep()
注意:如果遇到属性有proteted或者private,需要将字符串转码,防止出现无法复制的字符
urlencode(serialize(对象)) ==> url编码的序列化字符串:
结果:
O%3A5%3A%22Human%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A5%3A%22zhang%22%3Bs%3A10%3A%22%00Human%00age%22%3Bi%3A1%3Bs%3A8%3A%22%00%2A%00score%22%3Bi%3A100%3B%7D

2、反序列化

在php页面上,通过unserialize() 接收传入的序列化字符串,还原对象。

$obj = unserialize($_GET['str']);
url; xxx.php?str=O%3A5%3A%22Human%22%3A3%3A%7Bs%3A4%3A%22name%22%3Bs%3A5%3A%22zhang%22%3Bs%3A10%3A%22%00Human%00age%22%3Bi%3A1%3Bs%3A8%3A%22%00%2A%00score%22%3Bi%3A100%3B%7D
class Human{
    public $name="zhang";
    private $age=1;
    protected $score=100;
    //创建对象时候调用
    public function __construct(){
        echo "__contruct<br>";
    }
    //对象销毁时候调用
    public function __destruct(){
        echo "<br>__destruct";
    }
    //对象序列化时候调用
    public function __sleep(){
        return array('name', 'age', 'score');
    }
    //对象反序列化时候调用
    public function __wakeup() {
        echo "<br>__wakeup";
    }
}
$obj = unserialize($_GET['str']);//获取到浏览器传的序列化的结果,并执行反序列化
echo "<br>".$obj->name;//从反序列化的对象中获取变量name的值

序列化字符串中,只包含类名,属性名:属性值。 没有方法。