Fork me on GitHub

php面向对象

1. 面向对象典型例子

//一个典型的类
class Person{
    //注意这里用var定义,未确定用哪个关键词(protected,private,public)来修饰
    var $name ;
 
    //构造函数,
    function __construct($name){
        //通过构造函数传参来给类中的属性赋值
        $this->name = $name;
    }
    
    //说话这个方法
    function say(){
        echo "我的名字是".$this->name;
}

//实例化类.实例化后人就有了自己的专有特征,下面三个实例是不同的
$people1 = new Person("王王","男",20);
$people2 = new Person("李李","女",21);
$people3 = new Person("张张","男",22);

//每个具体的人都有自己的说法方式,能说出不同的内容
$people1->say() //我的名字是王王
$people2->say() //我的名字是李李
$people3->say() //我的名字是张张

总结:

  1. 一个类,可以有自己的属性,自己的方法,我们可以在构造函数中实现很多方法
  2. 实例化类是用new关键字,并且可以传入参数
  3. 访问这个实例化后的具体对象的方法是: 对象->属性 =xxxx
  4. 类和对象就像是,图纸和房子的关系,我们按照图纸施工就得到了一个有血有肉的真实的房子.这个过程就像是实例化,实例化后我们就可以在房子里做饭,洗衣服...

2. $this关键字

  1. $this在构造函数中指代该构造函数所创建的新对象,就是指当前对象
  2. 在当前类中使用属性和方法, $this->属性 或者 $this->方法
  3. 对象的方法内的局部变量,只在当前方法内有效,所以不使用$this关键字,直接使用
  4. 局部变量和类的属性要认清,可以同名,但是要注意区分,尽量不同名,以免混淆
class Person{

    var $name = "李四" ;
 
    function say($name){
        echo "我是类的属性中的name".$this->name;   
        echo "我是say方法中传递过来的参数".$name; 
        $this->dacnce();  //同样我们可以在say方法中调用person类中的dance方法;
    }
    
    function dance(){
        echo "我会跳霹雳舞";
    }
}

$people = new Person();
$people->say('张三');
//注意这里和上面例子中的区别,上面是在人实例化的时候就传入了初始属性,这里是给人的方法传入参数,注意理解

3. $parent关键字

  1. parent用来引用父类的方法
  2. parent::的追溯不仅于直接父类
## 一.子类继承父类
## 例子1
//父类
class employee{
    protected  $sal=3000;
    public function getSal(){
        $this->sal = $this->sal + 1200;
        return $this->sal ; 
    }
}
//子类对父类继承
class Manager extends employee {
    public function getSal(){
        // 这里调用了父类的方法,
        parent::getSal();
        //employee类中的return $this->sal 是为echo服务的
        //下面的$this->sal中的sal是通过继承得到的,而不是return回来的
        $this->sal = $this->sal + 1500;
        return $this->sal ;
    }
}
$emp = new employee();
echo "普通员工的工资是 " . $emp->getSal();

$manager = new Manager();
echo "经理的工资是: " . $manager->getSal();

//普通员工的工资是 4200
//经理的工资是: 5700

## 二.子类对父类属性重写

## 例子2.1
//父类的private属性不能被继承,如果父类有私有属性,那么父类的的方法只为父类的私有属性服务
//父类 private $sal =3000
//子类 protected $sal = 5000

class employee{
    private  $sal=3000;
    public function getSal(){
        return $this->sal ;
    }
}

class Manager extends employee {
    protected  $sal=5000;
    
    public function getParentSal(){
        return parent::getSal();
    }
}


$manager = new Manager();
//子类并且有getsal方法,这个方法是子类继承了父类的getsal方法,但是父类的私有属性$sal并没有被继承,这个被继承的父类getsal方法还是为父类的私有属性$sal服务,而不为子类的$sal服务
echo $manager->getSal();  

echo $manager->getParentSal();

//输出结果是  3000    3000

## 例子2.2 
//子类将父类的属性重写的情况下
//父类 protected $sal =3000
//子类 protected $sal = 5000

class employee{
    protected  $sal=3000;
    public function getSal(){
        return $this->sal ;
    }
}

class Manager extends employee {
    protected  $sal=5000;
    
    public function getParentSal(){
        return parent::getSal();
    }
}


$manager = new Manager();
echo $manager->getSal();  
echo $manager->getParentSal();

//输出结果是  5000    5000

## 三.子类对父类方法重写

//子类重写的方法对当前private有效

class employee{
    private  $sal=3000;
    public function getSal(){
        return $this->sal ;
    }
}

class Manager extends employee {
    private  $sal=5000;
    //重写父类的方法
    public function getSal(){
        return $this->sal ;   //这里返回的是子类的private属性
    }
    
    public function getParentSal(){
        //这里返回的是父类的priavte属性
        return parent::getSal();
    }
}


$manager = new Manager();
echo $manager->getSal();  
echo $manager->getParentSal();

//输出结果是  5000    3000

4. static关键字

  1. static关键字用来修饰属性和方法
  2. static关键字不经过实例化就能使用,不根据实例的不同而改变
  3. 静态属性在内存中只有一份,为所有实例共用
  4. 使用方法是 类名::静态属性 类名::静态方法名 或者 使用self::调用当前类中的其它静态方法
  5. 静态方法不能调用非静态属性(也就是不能用$this关键字来调用非静态属性,更不能用self:非静态属性这种错误的方式调用)

5. const修饰

  1. const用来修饰常量,使用方法和静态属性一样 类名::常量名
  2. 常量不能被修改,修改会报错
  3. 常量要大写

6. final关键字

final关键字用于类和方法之前,final类不可以被继承,final方法不可以被覆盖(重写)

7. 抽象方法和抽象类

  1. abstract修饰一个类和方法

  2. 抽象类不能被实例化,实例化会报错

  3. 子类(非抽象类)继承父类(抽象类),这时候子类是可以被实例化的,不会报错

  4. 抽象类继承抽象类的话,不需要重写其中的抽象方法,但是此时子类仍然不能被实例化

  5. 抽象类继承抽象类目的是对抽象类进行扩展

  6. 抽象方法只有声明,没有具体的实现方法

  7. 抽象方法没有{},而是采用;结束

  8. 抽象方法在子类中必须被重写,如果不重写就会报错,同时要注意参数的个数.如果父类中没有抽象方法,子类继承的时候不重写也不会报错

  9. 如果有抽象方法,当前类必须被声明为抽象类(但是抽象类中可以有非抽象方法)

abstract class User{
    protexted $sal = 0;
    abstract function getSal();   //注意这里没有{}
}

8. 接口的定义和规范

  1. 接口是一种特殊的抽象类,只包含抽象方法和静态常量,没有其他类型的内容
  2. 接口的写法 : interface 接口名{}
  3. 接口抽象方法只能用public修饰,默认也是public权限,即使是final和abstract也不行
  4. 注意其他抽象方法是用abstract修饰的,这里不用,只需写法一直就可以了
  5. 接口中的静态常量就是用const修饰的就是了
interface User{
    function getName();  //这是个抽象方法,最后是以 ; 结束的
    //function getAge(){};  //注意这是个非抽象方法,这样会报错的
}

9. 接口的实现

  1. 接口实现使用implements
  2. 一个类可以实现多个接口(解决了php单继承问题)
  3. 同抽象类的继承一样,实现接口要实现其中的抽象方法,否则会报错
class Student{
    protect $grade ;
    public function getGrade(){
        return $this->grade;
    }
}

interface User{
    function getName();
}

interface Administrator{
    function setBulletin($_bulletin);
}

//可以一次实现多个接口
class Admin implements User,Administrator{
    function getName(){}
    function setBulletin($_bulletin){}
}

//可以实现继承并且实现多个接口
class Admin extend Student implements User,Administrator{
    function getName(){}
    function setBulletin($_bulletin){}
}

10. 多态

  1. 多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息将可以产生不同的结果,这种现象称为多态性
  2. 同一个操作作用于不同的类的实例,将产生不同的执行结果。也即不同类的对象收到相同的消息时,将得到不同的结果

11. 接口的作用

  1. 继承"基类"跟继承"接口"都能实现某些相同的功能,但有些接口能够完成的功能是只用基类无法实现的
  2. 接口用于描述一组类的公共方法/公共属性.它不实现任何的方法或属性,只是告诉继承它的类《至少》要实现哪些功能,继承它的类可以增加自己的方法.
  3. 使用接口可以使继承它的类: 命名统一/规范,易于维护
  4. 提供永远的接口。 当类增加时,现有接口方法能够满足继承类中的大多数方法,没必要重新给新类设计一组方法,也节省了代码,提高了开发效率.
# 下面是一个关于usb接口的例子
//首先定义一个usb接口
interface USB{

    public function run();
}

# 下面定义三个不同的类key,mouse,store,都实现了上面的接口
//键盘
class key implements USB{
    
    public function run(){
        $this -> init();
    }

    public function init(){
        echo "key running ..";
    }
}
//鼠标
class mouse implements USB{

    public function run(){
        $this -> init();
    }

    public function init(){
        echo "mouse running ...";
    }
}
//移动硬盘
class store implements USB{
    
    public function run(){
        $this -> initialize();
    }

    private function initialize(){
        echo "store running ..";
    }
}

//以上三种设备都要遵循接口的run方法


# 下面实现多态

//1.首先我们可以
$key = new key();
$Key->run();

$mouse = new mouse();
$mouse->run();

//上调用不同的类的相同名方法,会输出不同的东东,也就是说每个类里面的同名方法完成的功能可以是完全不同的

//2.我们可以更进一步,用多态实现其调用

class computer{
    public function useUSB($obj){
        $obj -> run();
    }
}

//实例化computer
$computer = new computer();

//给这个实例传入不同的对象(对象是根据接口实现的)
$computer -> useUSB(new mouse()); 
$computer -> useUSB(new store());
$computer -> useUSB(new key());

//3.再进一步,此时我们又有个声卡设备,
//如果按照传统的方式,我们需要创建声卡类并实现接口,然后实例化声卡类,调用声卡方法,没增加一种设备,就要多一种调用方法,多了就不容易维护了
//现在我们如果有了上面的方法,只需要创建新的声卡类,然后调用的时候还是使用computer中的useUSB方法,就可以了,这样看起来更容易维护,更容易扩展

12. 对象克隆 __clone()方法

  1. 在项目中,使用两个或多个一样的对象,重新new关键对象,并且赋予相同的属性,是比较繁琐的
  2. 使用__clone()方法,可以得到两个一模一样的对象,并且互相不干扰
  3. __clone方法中有this和that指针
class Person{

    var $name;
    var $age;
    
     //构造函数,
    function __construct($name='',$age=''){
        //通过构造函数传参来给类中的属性赋值
        $this->name = $name;
        $this->age = $age;
    }
 
    function say(){
       echo "我的名字是".$this->name;
       echo ",年龄是".$this->name;
    }
    
    function __clone(){
        //注意这里的this和that指针,$this指向复本people2,$that指向原本people1
        $this->name = "我是假的$that->name";
        $this->age = 30;
    }
}

$people1 = new Person("张三",20);
$people2 = clone $people1;
$people1->say();
$people2->say();

//结果:
//我的名字是张三,年龄是20
//我的名字是假的张三,年龄格式30

13. call方法

  1. 当我们调用的方法在对象内容不存在时候,会出错,并停止运行程序
  2. 我们可以使用call方法来弹出一个提示说此方法不存在,然后程序可以继续执行
class Test{

    //调用不存在的方法时候自动调用次方法,第一个参数是方法名,第二个参数是数组参数
    public function __call($methodName, $args){
        //我们可以在这里写一些处理逻辑
        print_r($args);
        echo "您传入的方法不存在";
    } 
}

$test = new Test();
$test->demo("one","two","three",)   //因为demo方法并不存在,所以会自动调用上面的__call方法
posted @ 2019-01-02 16:00  archer-wong  阅读(265)  评论(0编辑  收藏  举报