1.基本介绍
oop的三大特征:封装、继承、多态
封装就是把抽象出来的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只能通过被授权才能对数据进行操作。
1.1 封装的具体实现-访问修饰符
访问修饰符包括public、protected、private,分别是公开的、受保护的、私有的,访问修饰符对常用属性和成员方法都适用
优先级:public>protected>private

- public :在类的内部、外部、子类都可以访问
- protected:只能在本类和子类中使用
- private:只能在本类中使用
案例说明:
<?php
//访问修饰符案例
class Person{
public $name;
protected $age;
private $sex;
public function __construct($name,$age,$sex){
$this->name = $name;
$this->age = $age;
$this->sex = $sex;
}
//三种不同的访问修饰符
public function getName(){
echo '<br> name = '.$this->name;
}
protected function getAge(){
echo '<br> age = '.$this->age;
}
private function getSex(){
echo '<br> sex = '.$this->sex;
}
public function show(){
echo '<br> 属性age = '. $this->age;
echo '<br> 属性sex = '. $this->sex;
echo $this->getAge();
echo $this->getSex();
}
}
$p1=new Person('张三',23 ,'男');
//public修饰的属性和方法可以在任何地方使用
echo'<br> name = '. $p1->name;
echo '<br>'. $p1->getName();
//不能被调用,受保护的方法不能在类的外部使用
//echo '<br> age = '. $p1->age;
//echo '<br> sex = '. $p1->sex;
//不能被调用,私有的的方法不能在类的外部使用
//echo '<br> age = '. $p1->getAge();
//echo '<br> sex = '. $p1->getSex();
//要想调用 在本类中定义一个public的方法,把protected和private修饰的属性和方法在一个公开的方法中调用
echo $p1->show();
?>


1.2 如何访问protected和private属性的三种形式
- 使用魔术方法__get和__set来实现对protected和private属性的操作
<?php //访问修饰符案例 class Person{ public $name; protected $age; private $sex; public function __construct($name,$age,$sex){ $this->name = $name; $this->age = $age; $this->sex = $sex; } //使用__set方法修改属性 public function __set($pro_name,$pro_val){ //判断当前对象是否存在传入的变量 if(property_exists($this,$pro_name)){ $this->$pro_name = $pro_val; }else{ echo '<br>当前属性名不存在!!!'; } } //使用__get方法获取属性 public function __get($pro_name){ if(property_exists($pro_name)){ return $this->$pro_name; }else{ echo '<br>当前属性名不存在!!!'; } } } $p1=new Person('张三',23 ,'男'); //修改被protected和private修饰的属性 echo '<br>' .$p1->age=24; echo '<br>' .$p1->sex='女'; ?>
优缺点:
- 优点:简单,一对__set和__get就可以搞定所有的private和protected修饰的属性
- 缺点:不够灵活,没有办法对各个属性进行控制和验证
- 对每个private和protected属性都提供一对get和set方法,这个就可以对每个属性进行单独的验证和控制
<?php //访问修饰符案例 class Person{ public $name; protected $age; private $sex; public function __construct($name,$age,$sex){ $this->name = $name; $this->age = $age; $this->sex = $sex; } //使用setXxx方法验证修改age属性 public function setAge($age){ //判断传入的值是不是数字且要大于0 if(is_numeric($age) && $age > 0 ){ $this->age= $age; }else{ echo '<br>当前属性值格式不正确!!!'; } } //使用getXxx方法获取age属性 public function getAge(){ return $this->age; } //使用setXxx方法验证修改sex属性 public function setSex($sex){ //判断传入的值是不是数字且要大于0 if($sex=='男'|| $sex == '女' ){ $this->sex= $sex; }else{ echo '<br>当前属性值格式不正确!!!'; } } //使用getXxx方法获取sex属性 public function getSex(){ return $this->sex; } } $p1=new Person('张三',23 ,'男'); //修改被protected和private修饰的属性 $p1->setAge(24); echo '<br>' .$p1->getAge(); $p1->setSex('女'); echo '<br>' .$p1->getSex(); ?>
优缺点:
- 优点:可以对每个属性进行验证,很灵活
- 缺点:会造成比较多的setXxx和getXxx方法,但这个也没什么大的问题
- 推荐使用这样的方法
- 写一个成员方法,可以根据业务逻辑,一次性对多个属性批量操作
<?php //访问修饰符案例 class Person{ public $name; protected $age; private $sex; public function __construct($name,$age,$sex){ $this->name = $name; $this->age = $age; $this->sex = $sex; } //使用setXxx方法验证修改age属性 public function setAge($age){ //判断传入的值是不是数字且要大于0 if(is_numeric($age) && $age > 0 ){ $this->age= $age; }else{ echo '<br>当前属性值格式不正确!!!'; } } //使用getXxx方法获取age属性 public function getAge(){ return $this->age; } //使用setXxx方法验证修改sex属性 public function setSex($sex){ //判断传入的值是不是数字且要大于0 if($sex=='男'|| $sex == '女' ){ $this->sex= $sex; }else{ echo '<br>当前属性值格式不正确!!!'; } } //使用getXxx方法获取sex属性 public function getSex(){ return $this->sex; } //创建一个成员方法,获取修改信息 public function undate($age,$sex){ $this->setAge($age); $this->setSex($sex); } //创建一个展示用户信息的方法 public function show(){ echo '年龄是 ' .$this->age; echo '性别是 ' .$this->sex; } } $p1=new Person('张三',23 ,'男'); //修改被protected和private修饰的属性 $p1->undate(24,'女'); $p1->show(); ?>
1.3 在开发中如何选择操作方式
- 如果我们希望直接通过$对象名->属性名的方式来操作属性,则使用__get和__set函数即可
- 如果我们希望使用各个属性分别进行验证则使用setXxx和getXxx
- 如果我们希望同时操作多个属性则选择第三种
1.4 封装的细节说明
- 普通属性要定义为public 、protected和private之一,如果var定义,则被视为公有,静态属性可以不指定访问修饰符,默认为public

- 类中的方法可以被定义为公有、私有、受保护的,如果没有定义默认是public
1.5 对象运算符连用
案例:通过一个学生对象,可以访问到该学生所在班级的信息.
<?php
//通过一个学生对象,可以访问到该学生所在班级的信息.
//定义一个学生类
class Student{
public $name;
private $school;
public function __construct($name,$school){
$this->name = $name;
$this->school = $school;
}
public function getSchool(){
return $this->school;
}
public function setSchool($school){
$this->school=$school;
}
}
//定义一个学校类
class School{
public $name;
public $address;
private $my_class;
public function __construct($name,$address,$my_class){
$this->name = $name;
$this->address = $address;
$this->my_class = $my_class;
}
public function getMyClass(){
return $this->my_class;
}
public function setMyClass($my_class){
$this->my_class=$my_class;
}
}
//定义一个班级类
class Myclass{
protected $name;
protected $stu_num;
private $introduce;
public function __construct($name,$stu_num,$introduce){
$this->name = $name;
$this->stu_num = $stu_num;
$this->introduce = $introduce;
}
public function getIntroduce(){
return $this->introduce;
}
public function setIntroduce($introduce){
$this->introduce=$introduce;
}
}
//首先创建班级对象
$myClass = new Myclass('1107' , 2, '学习的班级');
//创建学校对象
$school = new School('我的学校' , '陕西',$myClass);
//创建学生对象
$student = new Student('张三', $school);
var_dump($student->getSchool()->getMyClass()->getIntroduce());
?>

吾爱乐享

















































