1.基本介绍
oop的三大特征:封装、继承、多态
封装就是把抽象出来的数据和对数据的操作封装在一起,数据被保护在内部,程序的其他部分只能通过被授权才能对数据进行操作。
1.1 封装的具体实现-访问修饰符
访问修饰符包括public、protected、private,分别是公开的、受保护的、私有的,访问修饰符对常用属性和成员方法都适用
优先级:public>protected>private
- public :在类的内部、外部、子类都可以访问
- protected:只能在本类和子类中使用
- private:只能在本类中使用
案例说明:
代码语言:javascript复制<?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 对象运算符连用
案例:通过一个学生对象,可以访问到该学生所在班级的信息.
代码语言:javascript复制<?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());
?>