### 封装
程序只能通过被授权的成员方法才能对数据操作。如:电视机
* var $name; //var表示public
* 方法没有写属性,默认public
![](https://box.kancloud.cn/81205b238376d1c261e8f7630c260318_397x153.png)
protected,private可以通过公开的方法调用
~~~
class clerk{
public $name;
private $salary;
public function __construct($name,$salary){
$this->name=$name;
$this->salary=$salary;
}
public function getSalary($pwd){
if($pwd=='123'){
echo $this->salary;
}else{
echo '沒有訪問權限';
}
}
}
$a=new clerk('田偉',100000);
echo $a->name;
echo $a->getSalary(124);
~~~
### 访问proteced,private的数据3种方式:
* __get(),__set()可以一次性解决所有私有属性的操作。优点是简单,缺点是不够灵活,防护性比较差
~~~
<?php
class clerk{
public $name;
protected $nickname;
private $salary;
public function __construct($name,$nickname,$salary){
$this->name=$name;
$this->salary=$salary;
}
//魔術方法
public function __get($pro_name){
if(isset($this->$pro_name)){
return $this->$pro_name;
}else{
return '用戶名不存在';
}
}
public function __set($pro_name,$val){
if(isset($this->$pro_name)){
return $this->$pro_name=$val;
}else{
return '屬性不存在';
}
}
}
$a=new clerk('田偉','小偉',100000);
echo $a->name;
echo $a->nickname;
~~~
![](https://box.kancloud.cn/c83b28170afa62e3cdce320b8c821d05_733x58.png)
*给每个proteced ,private变量提供一个getXXX,setXXX方法。
在方法里可以进行各种效验
~~~
<?php
class Book{
public $name;
public $author;
public $price;
private $amount=0;
function __construct($name,$author,$price){
$this->name=$name;
$this->author=$author;
}
//amout的方法
public function setAmount($num){
if(is_int($num)){
return $this->amount=$num;
}else{
echo '格式錯誤';
}
}
public function getAmount($code){
if($code=='123'){
return $this->amount;
}else{
echo '密碼錯誤';
}
}
}
$book1=new Book('紅樓夢','小曹',200);
echo $book1->setAmount('1e');
echo $book1->getAmount('123');
~~~
* 直接在类里面写一个public方法,查询私有属性
### 对象运算符的连用
![](https://box.kancloud.cn/2f03f95a46eb8c9db0ecbfb08683bf07_374x220.png)
![](https://box.kancloud.cn/f3cbe6665ddc12b254b5a84d7f0d9e6c_707x273.png)
![](https://box.kancloud.cn/92ebde61a78480a94566cd88cc00ffd8_505x135.png)
## 继承
继承父类的属性和方法
目的是:减少代码的冗余
**继承是建立了子类与父类的查找关系,不是拷贝了父类。**
* 数据操作的时候,先在子类里面看查找属性或方法,如果子类有,就不会查找父类。如果没有,查找父类。
* 因此子类的属性或方法会覆盖父类的。
* 子类最多只能继承一个父类(可以父类再继承父类解决)
* 子类可以继承父类的public,proteced属性或方法
* 在创建子类对象时,如果没有定义构造方法,默认调用父类的构造方法
* 子类中访问父类的方法:父类::方法名,parent::方法名
* 如果子类方法和父类方法重名,称为方法重写。
子类调用父类的普通方法,用`$this->方法名,或parent::方法名`,或 父类名::方法名(不建议用)
子类调用父类的构造方法,用`parent::__construct();`
## 方法重载
传统重载:同一个函数名,通过参数的不同,调用不同的方法体
PHP的重载:动态的创建属性和方法,通过魔术方法实现的。
**非静态方法重载:__call**
调用一个不可用或不存在的方法时,call会被触发
**静态方法重载:__callStatic**
![](https://box.kancloud.cn/8193bd36de8f975dc2a831af10bc3a52_550x331.png)
## 属性重载
通过__set,__get来实现属性重载
![](https://box.kancloud.cn/766f256c11fecb69eb0f090282ac1be6_614x443.png)
## 方法重写(覆盖)
* 方法名和参数个数必须保持一致,类型约束也必须一致(参数的数据类型)
* 子类不能缩小父类的访问权限,父类是proteced,子类是public,子类父类会同时调用。
![](https://box.kancloud.cn/3328f795c468fe16af52f2d9512c7b62_462x310.png)
如果子类没有覆盖父类,子类里面可以用:this->方法名,如果覆盖了,使用父类要 parent::方法名
parent::属性名,只能用于父类的静态属性。而且为public或proteced,不能用于非静态属性。
## 属性重写
public ,proteced可以被重新,private不能被重写
## 多态
对象在不同情况下的多种状态,通过继承父类或接口方式实现多态
根据传入的对象类型不同,调用对应的对象方法
![](https://box.kancloud.cn/848adb31cd26006bec282b2141a40cb5_432x335.png)
## 抽象类
* 如果有一个方法不确定,可以把这个方法声明为抽象,抽象方法不能有函数体,
* 此类必须声明为抽象类
* 抽象类可以包含非抽象方法,可以没有抽象方法
* 抽象类可以有成员属性和常量
* 抽象类最主要目的在于设计,不在于实现,定义规范,让其他类来继承,并实现它的方法
* 抽象类不能被实例化
* 如果一个类继承了一个抽象类,必须实现所有的抽象方法。
![](https://box.kancloud.cn/f147228b44c86c46d3ccebd4fdb86e96_342x93.png)
~~~
abstract public funciton cry();
~~~
## 接口
接口不能被实例化
接口中所有的方法都不能有主体
一个类可以实现多个接口,逗号隔开
接口中可有属性,只能是常量 const TAX_RATE=0.08;
使用 iAbc::TAX_RATE;
接口中所有的方法都必须是public
接口不能继承其他的类,但是可以继承其他接口
![](https://box.kancloud.cn/6287b6a1e86227f01af683afe53ed35d_393x186.png)
![](https://box.kancloud.cn/3567017b04ccad3e530360e2c3e0c19f_429x120.png)
接口是小写的i开头,驼峰法
![](https://box.kancloud.cn/d57aa0d8afcf06e642df7bcf31b1b9a4_438x268.png)
![](https://box.kancloud.cn/ea6c4c9bc24170d7913e28626a63d3c7_476x175.png)
![](https://box.kancloud.cn/361c5e610ae5a413502f31658dd98309_261x86.png)
![](https://box.kancloud.cn/a7f23a5708184a72fce1fe0e19b3b1d1_440x166.png)
## final关键字
final方法在父类中,不能被子类重写覆盖
如果类为final,此类不能被继承
final方法是可以被实例化的
类为final,方法就没必要再写final