首页 > 代码库 > 面向对象小结

面向对象小结

 

## 典型例子
```
//一个典型的类
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. 类和对象就像是,图纸和房子的关系,我们按照图纸施工就得到了一个有血有肉的真实的房子.这个过程就像是实例化,实例化后我们就可以在房子里做饭,洗衣服...


## $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(‘张三‘);
//注意这里和上面例子中的区别,上面是在人实例化的时候就传入了初始属性,这里是给人的方法传入参数,注意理解

```

## $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
```

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


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


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


## 抽象方法和抽象类

1. abstract修饰**一个类和方法**
2. 抽象类不能被实例化,实例化会报错
3. 子类(非抽象类)继承父类(抽象类),这时候子类是可以被实例化的,不会报错
4. 抽象类继承抽象类的话,不需要重写其中的抽象方法,但是此时子类仍然不能被实例化
5. 抽象类继承抽象类目的是对抽象类进行扩展


1. 抽象方法只有声明,没有具体的实现方法
2. 抽象方法没有{},而是采用;结束
3. 抽象方法在子类中必须被重写,如果不重写就会报错,同时要注意参数的个数.如果父类中没有抽象方法,子类继承的时候不重写也不会报错
4.  如果有抽象方法,当前类必须被声明为抽象类(但是抽象类中可以有非抽象方法)
 
```
abstract class User{
    protexted $sal = 0;
    abstract function getSal();   //注意这里没有{}
}
```

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

## 接口的实现
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){}
}
```
## 多态
1. 多态性是指相同的操作或函数、过程可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息将可以产生不同的结果,这种现象称为多态性
2. 同一个操作作用于不同的类的实例,将产生不同的执行结果。也即不同类的对象收到相同的消息时,将得到不同的结果


## 接口的作用
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方法,就可以了,这样看起来更容易维护,更容易扩展

```

## 对象克隆   __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
```

## 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方法
```

 

以上是依据狂飙php的教程总结,如有理解错误请指正.

面向对象小结