面向对象1
<?php
class person{
/**
* 成员属性
* 在类中声明成员属性时,变量前面一定要使用一个关键字
* 例如,public,private,static等
* 如果不需要有特定意义的修饰,就使用var关键字
* 如果没有任何访问控制修饰,默认的就是public
* 其中,private只有在同一个类中才能访问,protected在同一个类中和子类中可以被访问,public则是外部成员都可以访问
*/
var $name;
private $sex;
private $age;
static $count;
function say(){
echo "speak";
}
function eat($food){
echo "eat $food";
}
/**
* 成员属性age是私有成员,采用了信息隐蔽
* 只有在对象内部成员方法中使用如果允许用户对私有属性进行赋值操作
* 解决办法就是在对象的内部声明一些操作私有属性的公有方法,而且可以加上限制条件,避免一些非法操作
* 因为信息隐蔽,私有成员不能对外“公布”,但是可以通过在类中创建一个公有接口,实现功能
* 与上面不同的是,如果是public属性,外部可以随意更改,包括一些非法操作
*/
function setsex($age){
if ($age>150||$age<0)
return ;
$this->age=$age;
}
//构造方法
function __construct($name="",$sex="男",$age=40){
$this->name=$name;
$this->sex=$sex;
$this->age=$age;
self::$count++;//测试对象被创建过多少次
//如果在类的内部的成员方法中访问其他的静态成员,通常使用self的形式访问,最好不要直接使用类名称
}
//析构方法
function __destruct(){
// echo "再见".$this->name."<br />";
}
/*
* 魔术方法,当外部调用对象中不存在的方法,则自动调用对象中的__call()方法。
* 当调用对象中不存在的方法时就会出现系统报错,然后程序退出不能继续执行,这个方法可以
* 当调动方法不存在时候执行,并可以继续向下执行。
*/
function __call($functionName,$args){
echo "你所调用的函数:".$functionName."(参数:";
print_r($args);
echo ")不存在!<br />\n";
}
/**
* 魔术方法toString,当在外部直接输出对象的引用的时候调用这个方法
*/
public function __toString(){
return $this->age;
}
/**
* 面向对象的封装性包含两个含义:
* 1,把对象的全部成员属性和全部成员方法结合在一起,形成一个不可分割的独立单位(即对象)。
* 2,信息隐蔽,即尽可能隐蔽对象的内部细节,对外形成一个边界,只保留有限的对外接口使之与外部发生联系
*
* 如果属性没有被封装,就会别随意的赋值,甚至是非法的值,对对象进行破换
* 现在上面的例子对age完成了封装,即定义为private,但是想要在外部完成赋值的操作,可通过在类中定义一个方法
* 如下,对象内部声明一些操作私有属性的公有方法,而且可以增加一些自定义的限制条件
*/
public function setAge($age){
if($age>150||$age<0){
return ;
}
$this->age=$age;
}
/**
* 一般把类中的成员属性定义为private的,这更符合现实的逻辑,因为能更好的对类中的成员起到保护作用
* 但是对成员属性的读取和赋值操作是非常频繁的,这时候如果在类中为每个私有的属性都定义可以在对象的外部获取和赋值的共有方法,又非常繁琐
* 所以PHP中提供了__set(),__get(),__isset(),__unset()等预定义方法,它们都有特定的作用
* 这些方法又叫做魔术方法,这些方法不需要我们主动调用,是当使用的时候自动调用,具体的见下面的代码
* 可以在这些方法前面加上private关键字修饰,防止用户直接调用它,但是使用的时候报错了,提示必须使用public
*/
/*
* set方法,控制在对象外部只能为私有的成员属性赋值,而不能获取私有属性的值
* 声明魔术方法需要两个参数,直接为私有属性赋值时自动调用,并可以屏蔽一些非法赋值
*/
public function __set($propertyName,$propertyValue){
if ($propertyName=="sex"){
if (!($propertyValue=="男" || $propertyValue="女")){
return ;
}
}
if ($propertyName=="age"){
if ($propertyValue>150 || $propertyValue<0){
return ;
}
$this->$propertyName=$propertyValue;
}
}
/**
* 实现的逻辑是:
* 返回年龄大于30自动减10返回,小于30返回真实年龄
* 如果是要返回性别,则返回保密,其他的私有成员直接返回
*/
public function __get($propertyName){
if ($propertyName=="sex"){
return "保密";
}elseif ($propertyName=="age"){
if ($this->age>30){
return $this->age-10;
}else {
return $this->$propertyName;
}
}else {
return $this->$propertyName;
}
}
/*
* isset()函数是用来测定变量是否存在的函数,参数是变量,返回的是布尔值
* 那是否能用这个方法对对象中的成员属性进行测定呢
* 如果是属性是公有的,那么可以使用这个方法,但是如果私有的,那么就被封装了,对象的属性对外部不可见
* 这个时候就可以使用魔术方法__isset();
* 同理,魔术方法__unset(),可以将私有成员属性删除,下面列举这两种方法
*/
public function __isset($propertyName){
if ($propertyName=="name"){
return false;//限制条件,不允许在外部测定name这个属性
}
return isset($this->$propertyName);//其他的属性都可以被测定,并返回测定结果
}
public function __unset($propertyName){
if ($propertyName=="name"){
return ;//限制条件,不允许删除变量name,但是在本例中因为name是公有属性,所以删除属性时候不会经过这个方法,所以这个
//逻辑实现不了,但是可以应用在其他私有成员上面
}
unset($this->$propertyName);
}
}
?>