php面向对象知识总结

面向对象是很重要的软件开发方法,可以说我们做开发的离不开它。

说到面向对象,那我们肯定会涉及到很多东西,比如类,函数,属性,方法等

因为是自己总结的,知识点比较零散,所以我会以概念+自身理解+代码示例来进行总结!


类的属性和类的方法

本质是变量 在类中就是类的属性 必须用var 或者 public private protected 等 用法: 对象->属性名

类的方法 也就是函数 用法:对象->方法名

class know {
    var $ccc = 123;//本质是变量 在类中就是类的属性  必须用var 或者  public private protected 等  用法:  对象->属性名
    public  function  b(){//类的方法  也就是函数    用法:对象->方法名
echo  111;
}
}

$a = new know();

print_r($a->b());//111
print_r($a->ccc);//123

类常量

和类中的变量不同 必须要赋值

放在一个类中 只能由这个类调用

const 常量名

调用 类名::常量名

class normal{
    const zzs = 111;
}
$n = new normal();
echo $n::zzs;

构造方法

在类中定义的 在实例化类的时候 会自动调用的方法

方法名字 __construct

通常用来 简化对象属性的初始化工作 还有一些要自动处理的 也可以写入里面

class construct{
    var $aa ;
    public  function __construct($a,$b){
        $this->aa = $a;
    }
    function  aaa(){
        echo $this->aa;//this调用构造函数中的变量
    }

}
class B extends construct{
    public function __construct()
    {
        echo 'B中的构造方法!';
        parent::__construct(100,2);//调用父类的构造方法
        
    }
}
$a  = new B() ;
var_dump ($a);

访问修饰控制符

三个关键字 public protected private

修饰符就是用来表明 这个属性或者方法的 可访问成都的关键词

public 公有 谁都可以访问 类似var var是public的同义词 但是var只能修饰属性 public 可以修饰方法和属性

private 私有 只有自己才可以访问

protected 保护 只有相关继承的类可以访问 a继承b B继承c ABC都可以访问

class con {
    public $a = '';
    private $b = '';
    protected  $c = '';

    function __construct($a,$b,$c)
    {
        $this->a = $a;
        $this->b = $b;
        $this->c = $c;
    }

}

工厂模式

设计一个工厂类 可以接收一个参数 该参数代表某个类名 比如B 然后这个工厂类就可以生产出传过来的类B的对应的对象

class A{}

class B{}

//用来生产各种类的对象 因为类只是直接调用方法别无他用  因此用静态方法
class factory{
    static function GetObject( $class_name){
        $obj = new $class_name();
        return $obj;
    }
}

$a = factory::GetObject('A');
$b = factory::GetObject('B');
var_dump($a);
var_dump($b);

析构方法

在类中的一个方法 在一个对象被销毁后 会自动调用的方法

方法名 destructor

不能带参数对象什么时候被销毁:代码执行结束被销毁或一个对象没有变量引用它的时候

class  destructor{
    public function __destruct()
    {
        echo  111;
    }
}
$a = new destructor();
$a = new destructor();
$a = new destructor();
$a = new destructor();

类的继承

A类使用了B类的属性和方法 说明A继承了B

派生

A继承了B 也就是说 B派生出了A

父类 子类

父是基类 也就是上一级的类

子是继承类 派生类 下一级的类

单继承:

一个类只能从上一级的类继承他的信息 php大部分的面向对象都是单继承

class animal {
    public  function  a (){
        echo 'aaa';
    }
}
class duck extends animal{
    public function  b(){
        echo 'bbb';
    }
}
$q  = new duck();
var_dump($q->a());//调用duck继承的类里面的a方法
var_dump($q->b());//调用duck的里面的b方法

最终类 和 最终方法

定义一个类 并预先设定好 不允许别的类来继承 也就是没有后代

最终类:final 类{}

最终方法 final 访问控制修饰符(可有可无) function 方法名(){}

final class A{
    final public function a(){

    }
}
class b{
    final public function a(){

    }
}

重写override

子类重新定义父类继承给自己的属性或方法

基本特征是:父类已经有的属性或者方法 子类用同样的名字重新定义 参数不能减少 必须和父类一致

对于构造方法 没有参数的要求

重写也叫覆盖

重写的原因:一般来说 子类的特征信息的定义 一般比父类更详尽

父类没有的 子类可以有 例如添加特征信息

父类有的 子类也可以有 但是子类可以最定义得更加详细

重写的要求:

父类是 public 子类只能是public

父类是 protected 子类只能是 protected public

父类是 private 子类不能重写覆盖

 

class Animal {
     public $blood = 0;
     public function eat(){
        echo '动物类的吃';
        $this->blood+=1;
     }
 }
 class pig extends Animal{
    public $blood = 1;//属性重写
     public function eat(){//方法重写
        echo '猪的吃';
        $this->blood+=2;
     }
 }
 class duck extends Animal{
    public $blood = 2;//属性重写
     public function eat(){//方法重写
        echo '鸭子的吃';
        $this->blood+=3;
     }
 }



class A{
     public $name = '';
     protected $age = '';
     private $sex = '';
 }
 class B extends A{
      public $name = '1';
      protected $age = '1';
      private $sex = '1';
 }

 $b = new B();
 echo '
';
 var_dump($b);

parent 关键字

用在子类中 访问父类的方法或属性

用法:parent::属性或方法或父类名字::属性或方法

class A {
     public $name ='';
     public $age ='';
     public $sex ='';

     public function __construct($name,$age,$sex){
        $this->name = $name;
        $this->age = $age;
        $this->sex = $sex;

     }  
 }

class B extends A{
    
    //接受参数
    public function __construct($name,$age,$sex)
    {
        //调用父类的构造方法  两种方法 一种是直接类名 一种是parent
        A::__construct('1','2','3');
        parent::__construct('4','5','6');

        
    }
}
 $a = new  B('ZZS','','');
var_dump($a) ;

单例模式

多次调用 只能实例化同一个对象

不会重复

class single{
    //定义一个私有的静态属性用来装一个对象  外界无法访问
    private static $s = null;
    //私有构造方法 不让外界new对象
    private function __construct()
    {
        
    }
    //给外界提供一个方法  让他从这个方法来获得一个对象
    static function Getone(){
        if(empty(self::$s)){//如果还没被实例过
            self::$s =  new self();
            return self::$s;

        }else{
            //否则就直接返回刚才的对象
            return  self::$s;
        }
    }
}
$obj = single::Getone();
$obj1 = single::Getone();
var_dump($obj);
var_dump($obj1);

静态属性 和静态方法

所谓的静态 就是只属于这个类的属性和方法

类中的属性名和方法名 用static

写法:

static $属性名

static function

使用:

类名::$属性名

类名::方法名

class Math{
    static  $a = 0;
    static  function  b ($x,$y){
        $q =  $x * $x + $y*$y;
        return pow($q,0.5);

    }
}
$aaaa = Math::$a;//调用类中的静态属性
var_dump($aaaa);
$vvv = Math::b(2,2);//调用类中的静态方法
var_dump($vvv);

this和self

$this 代表调用当前方法的对象

只能用于在一个类定义语法的内部 通常不在静态方法中(无法使用)

self 代表当前单词所在的类的本身 既可以用在静态方法中 也可以用在普通方法中

只能用于在一个类定义语法的内部

class total {
    static  $a = '1';
    var $b = '2';
    function  b_f(){
        echo 'b_f';
        var_dump($this->b);//类中用this调用属性
        var_dump(self::$a);//类中用self调用静态属性
    }

    static function  a_f(){
        echo 'a_f';
        var_dump(self::$a);//类中用self调用静态属性
//        var_dump($this->b);//类中用$this调用属性  会报错
    }

}

$t =  new total();
var_dump($t->b_f());//调用方法
$t->b;//调用b属性

total::$a;//调用静态属性
total::a_f();//调用静态方法
var_dump(total::a_f());//调用静态方法

抽象类

一个不能被实例化的类

abstract 类名

抽象方法 什么也不做的方法 基本上跟抽象类一起使用 没有方法体 只有方法头

abstract function 方法名(形参1,形参2)

 

抽象类和抽象方法的关系

一个类中有抽象方法 该类就是抽象类

一个抽象类中可以没有抽象方法

子类继承于一个抽象类

要么子类必须实现父类中的所有抽象方法

要么子类也做抽象类,此时可以不实现父类的抽象方法 当然去实现也可以

子类实现抽象父类的方法 访问控制修饰符的范围不能降低 且方法的参数必须一致 相当于重写

abstract class Animal {
    protected $blood = 100;
    function Attack(){
        echo '发动攻击';
        $this->blood--;
    }
    abstract function a();
 }
 class tiger extends Animal{
     function Attack()
     {
         echo  '老虎发动攻击';
         $this->blood-=2;
     }
 }

 class fish extends Animal{
    function Attack()
    {
        echo  '鱼发动攻击';
        $this->blood-=1;
    }
}

接口 关键字 interface

是比抽象类更抽象的类似的一种结构

接口中 只有这两种成员 常量和抽象方法

接口类中的方法都是抽象类 但是不需要用 abstract这个关键字来声明

 

为什么需要接口

面向对象的单继承是对‘现实世界’的多继承现象的一种妥协 为了不使代码过于复杂

但有时候 又往往需要多继承的情形需要描述

于是 使用接口这种技术 可以做到多继承

 

接口中的常量和抽象方法 都只能是public 而且不用写

抽象方法 无需使用abstract

对接口的继承 不叫 extends 而叫实现 implements

class 类 implements 接口1,接口2,接口3{

}

interface Player{
     function play();
     function next();
     function prev();
     function stop();


 }

 interface Usb{
    const width = 12;
    const heigt = 5;
    function data_in();
    function data_out();
 }
//zzs 实现 以上两个接口中的抽象方法
 class zzs implements Player,Usb{
    function play(){}
    function next(){}
    function prev(){}
    function stop(){}
    function data_in(){}
    function data_out(){}
 }

 /**
  * 另外  
  * 一个类 也可以继承其他类 并同时实现 其他接口  
  */
  class A extends B implements Player,Usb{

  }
  //接口之间也可以进行继承  可以实现多继承

  interface zz extends Player,Usb{

  }

重载 overload(方法重载)

方法重载 当对一个未定义的方法进行调用的时候 会自动调用 预先设定的好的魔术方法

使用一个对象或者类的时候 如果访问了其并没有定义的(即不存在的)的属性或方法

则会使用某些预先定义好的特殊方法来应对这种情况

是一种应对非法使用对象或类的措施

 

__call()

当对一个对象未定义的实例方法进行调用的时候 会自动调用预先定义好的魔术方法

__callstatic()

当对一个对象未定义的静态方法进行调用的时候 会自动调用预先定义好的静态魔术方法

class A{
     public function a1(){
         echo '

a1实例方法'; } //第一个参数表示不存在的方法名字 //第二个参数表示调用不存在的方法时的所有实参 是一个数组 array function __call($name, $arguments) { var_dump($name);//输出调用不存在的方法的名字 var_dump($arguments);//输出调用不存在方法的时候 传的参数 并装成一个数组 if($name == 'eat'){ $num = count($arguments); if($num == 1){//调用喝粥方法 $this->hezhou($arguments[0]); }else{ $this->chifan($arguments[0],$arguments[1]); } } } function hezhou($p1){ echo '一口吃完'.$p1; } function chifan($p1,$p2){ echo '使用'.$p2.'一口吃完'.$p1; } //静态魔术方法 static function __callStatic($name, $arguments) { } } $a = new A(); var_dump($a->a1()); var_dump($a->a12('1','2','3')); $a->eat('1');

 

重载 overload(属性重载)

属性重载 在定义一个类的时候 预先定义4个方法,来应对使用不存在的属性的时候的措施

使用一个对象或者类的时候 如果访问了其并没有定义的(即不存在的)的属性或方法

则会使用某些预先定义好的特殊方法来应对这种情况

是一种应对非法使用对象或类的措施

 

__set($name,$value)方法

对一个对象不存在的属性进行赋值的时候 会自动被调用

 

__get($name,$value)方法

对一个对象不存在的属性进行取值的时候 会自动被调用

 

__isset($name)方法

对一个对象不存在的属性进行isset()判断 会被自动调用

 

__unset($name)方法

对一个不存在的属性进行unset的时候 会自动调用

class Al{
    public $p1 = 1;
    //创建空数组 用来存储那些不存在的属性的赋值
    public $prop_list = array();
    function __set($name, $value){
        // echo '不存在!'.$name.'=>'.$value;
        $this->prop_list[$name] = $value;
        echo '
';
        var_dump($this->prop_list);
    }
    function __get($name){//$name代表取值的不存在的属性
        
        if( !empty($this->prop_list[$name])  ){
            return $this->prop_list[$name];
        }else{
            return  '属性不存在!';
        }

    }
    function __isset($name)
    {
        if(isset($this->prop_list[$name])){//如果确实存在  返回真
            return true;
        }else{
            return false;
        }
    }
    function __unset($name)
    {
        unset($this->prop_list[$name]);
    }
}
$a = new Al();
$a ->p1 = 2;//对一个存在的属性进行赋值
$a ->p2 = 11;//对一个不存在的属性进行赋值

$a->p1;//对一个存在的属性进行取值
var_dump($a->p2);//对一个不存在的属性进行取值

var_dump(isset($a->p1));
unset($a ->p3);
var_dump($a->prop_list);

类的自动加载 _autoload

当使用一个类 而这个类不存在的时候 就会去调用某个函数

在该函数中可以去加载要加载的类文件

以实现这个类的自动加载

 

自动加载的注意事项

 

通常我们将类文件取名为跟类名相关的有规律性的名字 类名.class.php

这个类文件中 只包含一个类的定义语句 不要有其他

类文件要集中放在一个文件夹中

//这个函数在后续代码中只要需要一个类 就会自动被调用 进行自动加载
//唯一参数 表示要找的类名
function __autoload($class_name){
    echo '没有这个类';
    require_once './'.$class_name.'.class.php';
}

$a = new zzs();
var_dump($a);

 

对象的克隆

新对象 = clone 旧对象

class A{
    public $na = 'zzs';
}
$a = new A();
$b = clone $a;
var_dump($a);//1号对象
var_dump($b);//2号对象

对象的遍历(foreach)

只能遍历可访问的属性

class A{
    public $p1 = 2;
    protected $p2 = 3;
    private $p3 = 4;
    static $p4 = 5;
    //用来显示对象的所有属性
    function showAll(){
        foreach($this as $prop => $value){
            echo "
"; } } } $a = new A(); //遍历该对象 会一次次的获取该对象的属性 //并将属性名赋值给$prop 属性值赋值给value foreach($a as $prop => $value){ echo "
"; } $a->showAll(); var_dump($a);

对象的序列化和反序列化技术

对象在进行序列化的时候 会自动调用类中的魔术方法 __sleep() 前提有这个方法

对象在进行反序列化的时候 会自动调用类中的魔术方法 __wakeup() 前提有这个方法

 

对于对象的序列化 如果__sleep()方法 此时w我们就可以人为控制序列化的细节

 在这个方法中必须返回一个数组 该数组存储了该对象要进行序列化的属性名

也就是 序列化的时候 可以选择哪些属性序列化

//举例  设计一个类  有三个属性 并实例化一个对象
 //将这个对象进行序列化 并控制只序列化其中两个属性 
 //然后在反序列 进行观察

 class time{
    public $n1 = 1;
    public $n2 = 2;    
    public $n3 = 3;    

    function __sleep(){//进行序列化的时候  会调用到的方法 __sleep() 
        //希望对象只序列化 n1 n3
        return array("n1","n3");
    }
 }

 $t = new time();

 $t->n1 = 11;
 $t->n2 = 22;
 $t->n3 = 33;

 //将这个对象进行序列化
 $str = serialize($t);
 //写入文件
 file_put_contents('./ob.txt',$str);

 //反序列化
 $zz = file_get_contents('./ob.txt');
 $res = unserialize($zz);
 var_dump($res);

其他魔术方法

与类相关的函数

class_exists() 判断某个类是否存在

interface_exists() 判断某个接口是否存在

get_class($对象) 获得一个对象的所属类

get_parent_class($对象) 获得一个对象的所属类的父类

get_class_methods(类名) 获得一个类的的所有方法名 结果是一个数组

get_class_vars(类名) 获得一个类的所有属性名 结果是一个数组

get_declared_classes() 获得所有类名

 

与对象有管的系统函数

is_object() 判断是否是对象类型

get_object_vars($对象) 获得一个对象的所有属性 不包含静态属性

 

与类相关的运算符

new 创建一个类的对象(实例)

instanceof 判断一个对象(变量) 是否是某个类的对象

class A{
    function f1(){
        echo '当前这个类'.__CLASS__;
        echo '当前方法为'.__METHOD__;
        echo '当前目录'.__DIR__;
        echo '当前文件'.__FILE__;
        echo '当前行为'.__LINE__;

    }
}

$a = new A();

var_dump($a->f1());

//instanceof 判断一个对象(变量) 是否是某个类的对象  是返回true 否返回false
//演示
class hh {
}
class hao extends hh{
}
$v1 = 1;
$v2 = new hh();
$v3 = new hao();
$res = $v1 instanceof hh;//v1不是hh的对象 所以 返回false
var_dump($res);

__tostring()和__invoke()

class A{
     public $name = 'zz';
     protected $age = 22;

     //当对象被当作字符串来使用的时候 进行调用
     function __toString()
     {
         echo "对象被当作字符串来使用";
     }

 }
class B{
     function __invoke()
     {
         echo '我是一个对象 不要当我是函数';
     }
 }
 $b = new B();
 //将对象当作函数来使用
 $b();

对象的类型转换

对象转对象 没有变化

数组转对象 键名当作属性名 值为对应值 整数下标的单元 转换为对象的属性后 无法操作

null转换为对象 空对象

其他标量数据转换为对象 属性名为固定的‘scalar’ 值为该变量的值

$s = new stdClass();

$conf = array(
    'host'=>'localhost',
    'user'=>'root',
    'pass'=>'root'
);
$c = (object)$conf;//强制类型转换   数组转对象

var_dump($c);
/***其他标量数据转换为对象  */  //属性名都是 scalar
$v1 = 2;   $v1c = (object)$v1;//整型转对象
$v2 = 2.2;   $v2c = (object)$v2; //浮点转对象
$v3 = "abc";   $v3c = (object)$v3; //字符串转对象
$v4 = true;   $v4c = (object)$v4; //布尔型转对象 
echo '
';
var_dump($v1c);
var_dump($v2c);
var_dump($v3c);
var_dump($v4c);

类型约束

只能在函数或方法的形参上进行约束

只能对数组 对象 类和接口进行约束

 

数组:使用array关键字

类:使用要求传递过来的实参对象必须是该类的对象

接口:要求传递过来的实参对象必须是实现了该接口的对象

class A{
    public function nam(){
        echo '111';
    }
 }
 interface I1{}
class b implements I1{}
 function f1($p1,Array $p2,A $p3, I1 $p4){
    //此时 p1没有约束  p2必须是传过来的是数组
    //p3必须是类A的对象 
    //p4必须是实现了接口 I1的对象
 }
 //实例化
 $a = new A();
 $b = new b();
 //调用函数
//  f1(1,2,3,4);//此时不满足约束 会报错 从第二个参数开始报错 表示第二个参数必须是数组
//  f1(1,array(
//      'host'=>'1111','sss'=>'2222'
//  ),3,4);//此时不满足约束 会报错   must be an instance of A  表示必须是A的实例(也就是A被实例化的对象)
 f1(1,array(
     'host'=>'1111','sss'=>'2222'
 ),$a,$b);//此时报错第四个参数   must implement interface I1  必须是实现接口I1的对象  (也就是继承实现I1的类)

变量的序列化和反序列化技术

序列化:将一个内存形态存在的变量的非持久数据 转换成硬盘形态存在的物理数据的过程

 

反序列化:将之前序列化之后的硬盘形态存在的物理数据 恢复为序列化之前的内存形态存在的变量数据的过程

 

变量数据序列化的过程分为两步:

将变量的serialize()函数进行处理 获得字符串结果 $str = serialize($v1) $v1是一个变量 自然也是一个数据

将字符串结果 保存为文件到硬盘中 file_put_contents("文件路径",$str)

 

磁盘数据反序列化的过程分为两步:

从文件中读取序列化的结果 $str = file_get_content('文件路径');

将字符串使用unserialize()j进行处理 获得原始数据 $v1 = unserialize($str)

//演示序列化
 $v1 = 1; $str1 = serialize($v1);
 $v2 = 2.2; $str2 = serialize($v2);
 $v3 = "acaca"; $str3 = serialize($v3);
 $v4 = true; $str4 = serialize($v4);
 $v5 = array(51,53,45); $str5 = serialize($v5);
 //将结果 写入并创建到一个文件中
file_put_contents('../record1.txt',$str1);//i:1;
file_put_contents('../record2.txt',$str2);//d:2.2
file_put_contents('../record3.txt',$str3);//s:5:"acaca"
file_put_contents('../record4.txt',$str4);//b:1
file_put_contents('../record5.txt',$str5);//a:3:{i:0;i:51;i:1;i:53;i:2;i:45;}

//演示反序列化
$str1 = file_get_contents('../record1.txt');$v1 = unserialize($str1);
$str2 = file_get_contents('../record2.txt');$v2 = unserialize($str2);
$str3 = file_get_contents('../record3.txt');$v3 = unserialize($str3);
$str4 = file_get_contents('../record4.txt');$v4 = unserialize($str4);
$str5 = file_get_contents('../record5.txt');$v5 = unserialize($str5);
var_dump($v1);
var_dump($v2);
var_dump($v3);
var_dump($v4);
var_dump($v5);

关于对象的相关知识就整理到这里,觉得有用的加个关注点个赞哦!

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

你可能感兴趣的:(PHP)