一、概念
封装性是面向对象编程中的三大特性之一,封装就是把对象中的成员属性和成员方法加上访问修饰符,使其尽可能隐藏对象的内部细节,以达到对成员的访问控制(切记不是拒绝访问)。
含义:
a.把对象的全部成员属性和全部成员方法结合在一起,形成一个不可分割的独立单位(即对象)
b.信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界(或者说形成一道屏障),只保留有限的对外接口使之与外部发生联系。
原则:要求对象以外的部分不能随意存取对象的内部数据(成员属性和成员方法),从而有效的避免了外部错 误对它的“交叉感染”,使软件错误能够局部化,大大减小差错和排错的难度。
PHP5支持如下3种访问修饰符:
public (公有的 默认的)
private (私有的)
protected (受保护的)
二、设置私有成员
只要在声明成员属性或成员方法时,使用private关键字修饰就是实现了对成员的私有封装。封装后的成员在对象的外部不能直接访问,只能在对象的内部方法中使用 $this访问。
既然封装为私有之后不能被对象外部直接赋值,也不能在对象外部直接获取私有属性的值,那么如果不让想在对象外部对私有属性进行一些操作则需要在对象的内部声明一些操作私有属性的共有方法。
1 <?php 2 3 /** 4 * 声明 Person 人这个类 5 */ 6 class Person 7 { 8 //私有成员属性 9 private $name; 10 private $sex; 11 private $age; 12 13 function __construct($name="",$sex="男",$age=1) 14 { 15 $this->name=$name; 16 $this->sex=$sex; 17 $this->age=$age; 18 } 19 20 //通过这个公有方法可以在对象外部获取私有属性$name的值 21 public function getName() 22 { 23 return $this->name; 24 } 25 26 //通过这个公有方法可以在对象外部为私有属性赋值,但限制了条件 27 public function setSex($sex) 28 { 29 if($sex=="男" || $sex=="女") 30 { 31 $this->sex=$sex; 32 } 33 } 34 35 //通过这个公有方法可以在对象外部为私有属性赋值,但限制了条件 36 public function setAge($age) 37 { 38 if($age>150 || $age<0) 39 return; 40 $this->age=$age; 41 } 42 43 44 public function say() 45 { 46 echo "我的名字是:{$this->name},性别:{$this->sex},年龄:{$this->age}<br>"; 47 } 48 } 49 50 $zhangsan=new Person("张三","男",40); 51 52 echo $zhangsan->getName()."<br>"; 53 $zhangsan->setSex("女"); 54 $zhangsan->setAge(200); 55 $zhangsan->say(); 56 57 ?>
上面代码中,声明一个Person类并将所有成员属性设置为私有属性,不让外部直接访问,但在内部做权限访问。构造方法没有加关键字默认是公有的方法(构造方法不要设置为私有的权限),用户可以通过使用构造方法创建对象并为私有属性赋值。还提供了一些可以在对象外部存取私有成员属性的访问接口。
三、魔术方法
__set(): 用于替代通用的set赋值方法
格式 [修饰符] function __set(string $name,mixed $value){ ... } 当我们直接为一个对象中非公有属性赋值时会自动调用此方法,并将属性名以第一个参数(string),值作为第二参数(mixed)传进此方法中。
__get(): 用于替代通用的get取值方法
格式:[修饰符] function __get(string $name){ ... } 当我们直接输出一个对象中非公有属性时会自动调用此方法,并将属性名以第一个参数传进去。
1 <?php 2 3 class Person 4 { 5 //下面是声明人的成员属性,全都使用了private关键字封装 6 private $name; //此属性被封装 7 private $sex; //此属性被封装 8 //声明魔术赋值方法;$propertyName :成员属性名、$propertyValue :成员属性值 9 public function __set($propertyName, $propertyValue) 10 { 11 $this->$propertyName = $propertyValue; 12 } 13 //声明魔术取值方法;$propertyName :成员属性名 14 public function __get($propertyName) 15 { 16 return $this->$propertyName; 17 } 18 } 19 $person1 = new Person( ); 20 $person1->name = "李四"; //自动调用了__set()方法为私有属性name赋值 21 $person1->sex = "女"; //自动调用了__set()方法为私有属性sex赋值 22 23 echo $person1->name; //自动调用魔术方法__get( )获取属性name值 24 echo $person1->sex; //自动调用魔术方法__get( )获取属性sex值 25 26 ?>
__isset(): 检测对象中成员属性是否存在
格式: [修饰符] function __isset(string $name){ ... } 当使用isset()或empty()判断一个对象的私有或受保护的属性是否存在时,会自动调用此方法。参数name表示被判断的属性名。
__unset(): 销毁对象中成员属性方法
格式: [修饰符] function __unset(string $name){ ... } 当使用unset( )销毁一个对象的私有或受保护的属性时,自动调用此方法,并将属性名以第一个参数传进去。
1 <?php 2 class Person { 3 private $name; //此属性被封装 4 private $sex; //此属性被封装 5 public function __construct($name="", $sex="男") { 6 $this->name = $name; 7 $this->sex = $sex; 8 } 9 public function __isset($propertyName) //需要一个参数,是测定的私有属性的名称 10 { 11 return isset($this->$propertyName); //其他的属性都可以被测定,并返回测定的结果 12 } 13 public function __unset($propertyName) //需要一个参数,是要删除的私有属性名称 14 { 15 if($propertyName == "name") //如果参数中传入的属性名等于“name”时条件成立 16 return; //退出方法,不允许删除对象中的name属性 17 unset($this->$propertyName); //在对象的内部删除在对象外指定的私有属性 18 } 19 } 20 $person1 = new Person("张三", "男"); //创建一个对象$person1,将成员属性分别赋上初值 21 var_dump( isset( $person1->name ) ); //输出bool(true),不允许测定name属性 22 var_dump( isset( $person1->sex ) ); //输出bool(true),存在sex私有属性 23 var_dump( isset( $person1->id ) ); //输出bool(false),测定对象中不存在id属性 24 unset( $person1->name ); //删除私有属性name,但在__unset()中不允许删除 25 unset( $person1->sex ); //删除对象中的私有属性sex,删除成功 26 27 28 ?>
注意:上面四个魔术方法只对类中的私有、受保护成员属性有效。 魔术方法前的修饰符可以是公有、私有,不影响调用。