php规定以两个下划线(__)开头的方法都保留为魔术方法
php是面向对象的语言,但是 之前的php语言还真不是,所以有一些面向对象的标准实现并不完善,例如重载。但我们可以通过一些魔术方法来弥补。
很多情况下,我们在创造对象的成员属性的时候,只有在某一刻才能确定下来,这在之前或者之后都不可以,但我们没有办法给我们的成员属性一个函数值(属性里面不支持),所以这个时候我们就需要一个特定的方法-——魔术手法
例如:
<?php class human{ //成员属性 var $name; var $sex function human(){ echo '#########'; //echo() 函数输出一个或多个字符串。 } function wawaku(){ echo '555555555~'; } } $one=new huamn; var_dump($one);
当我 方法名与类名相同的时候,我一创建$one=new huamn;
这个对象,就会输出echo '#########'
这就是创建之时,所以在之后,我添加这样一句话:
<?php class human{ //成员属性 var $name; var $sex //成员方法 //魔术方法1:构造方法 function human(){ echo '#########'; $this->sex = mt_rand(0,1) ? '男':'女'; } function wawaku(){ echo '555555555~'; } } $one=new human; var_dump($one); //var_dump() 函数用于输出变量的相关信息。
当我的构造方法里面有参数,
function human($a)
那么我的 $one后面也要加一个括号,并且填上相应的参数
$one=new human('a');
注:该方法仅仅只是举例,在实际生活中不建议使用。因为一旦我们更改类名,我们就必须将所有的human全部更改成相同的名字,否则构造失败
在实际生活中,我们更加常用的是使用函数,例如__construct()
<?php class human{ //成员属性 var $name; var $sex //成员方法 //魔术方法1:构造方法 function __construct($name){ $this->sex = mt_rand(0,1) ? '男':'女'; $this->name = $name; } function wawaku(){ echo '555555555~'; } } $one=new human('hcj'); var_dump($one);
所以,
简单来说,魔术方法是一种特殊的函数
__construct()是构造函数
触发时机:在对象实例化(创建对象)的时候自动触发
作用:初始化成员属性
参数:可以有,可以没有,取决于设定与逻辑
返回值:没有
注意:如果构造方法具有参数,且参数没有默认值,在实例化对象时,必须在类名后面的括号内添加实参
<?php class human{ //成员属性 var $name; var $sex; var $id; //成员方法 //魔术方法1:构造方法 function __construct($name){ $this->sex = mt_rand(0,1) ? '男':'女'; $this->name = $name; $this->id = uniqid(); //uniqid() 生成一个唯一的 ID } function wawaku(){ echo '555555555~'; } } $one=new human('hcj'); var_dump($one);
__desctruct()析构函数,不需要显示的调用,系统会自动调用这个方法。而且析构函数不需要参数(因为不需要调用)
触发时机:在销毁对象的时候自动触发(unset() 或者 页面执行完毕)
作用:回收对象使用过程中的资源,配合 unset 使用
参数:没有
返回值:没有
<?php class human { var $name; var $sex; var $id; function __construct($name){ $this->sex = mt_rand(0,1) ? '男':'女'; $this->name = $name; $this->id = uniqid(); //uniqid() 生成一个唯一的 ID } function __destruct($name){ echo '@@@@@@@@@@'; unset($this->id); } } $one=new human('hcj'); var_dump($one); unset($one); //注:在这里我们无法检测到,因为此时,one已经注销,无法查看id情况
**面向对象的三大特征:
封装特性:在一个对象产生之后,对象的部分成员属性和成员方法逻辑上是不允许对象外部调用或者使用的。这就是封装特性的由来
封装的关键字:private 私有的
private 的特征:
<?php var xiyiji { private $color = '白色'; var $pinpai = '海尔'; var $weight = '20kg'; var $rongliang = '6.5L'; private $mada = '三菱重工'; //成员方法 //洗衣服方法 private function xiyi() { echo '洗衣服'; $this->settime(); } private function tuoshui() { echo'脱水'; } private function settime() { echo'定时功能'; echo $this->mada.'开启定时功能'; } } //实例化一个洗衣服对象 $one= new xiyiji(); var_dump($one); echo $one->xiyi(); //发现可以调用, 洗衣服三菱重工开启定时功能 //尝试修改 private 修饰的成员属性值 '''$one->made = '学习园地'; var_dump($one);''' //发现查看,更改失败,所以我们需要魔术方法开一个后门 //魔术方法 __get()
魔术方法: __get(访问后门)
<?php var xiyiji { //成员属性 private $color = '白色'; var $pinpai = '海尔'; var $weight = '20kg'; var $rongliang = '6.5L'; private $mada = '三菱重工'; //成员方法 //洗衣服方法 private function xiyi() { echo '洗衣服'; $this->settime(); } private function tuoshui() { echo'脱水'; } private function settime() { echo'定时功能'; echo $this->mada.'开启定时功能'; } function __get($pro) { //__get 当我调用私有成员属性,就会调用这个方法,但不是所有的私有成员属性我都需要看,所以要有一个判断 if($pro == 'name'){ echo '######'; // echo $this->color; return $this->$pro; }else{ return '禁止查看'; } } } //实例化一个洗衣服对象 $one= new xiyiji(); var_dump($one); echo $xiyiji->color; echo '<hr/>'; echo $xiyi->settime; //xiyiji->color='red'; 发现失败
<?php class Person { //成员属性 var $name = '李兰英'; private $sex = '男'; var $age = '38'; //成员方法 function say(){ echo '佛爷吉祥'; } function nn(){ echo '哗啦啦啦啦~'; } //魔术方法 __set($a,$b){ $a 私有成员属性的原值 $b 私有成员属性的新值 function __set($a,$b){ if($pro == 'sex'){ echo '##'; //var_dump($a); //var_dump($b); $this->$a = $b }else{ echo '禁止修改 '; //没有返回值 } } } } //实例化对象 $lly = new Person; var_dump($lly); // 访问私有成员属性 // echo $lly->sex; // 设置私有成员属性 $lly->sex = '人妖'; var_dump($lly);
<?php class Person { //成员属性 var $name = '李兰英'; private $sex = '男'; var $age = '38'; //成员方法 function say(){ echo '佛爷吉祥'; } function nn(){ echo '哗啦啦啦啦~'; } //魔术方法 __set($a,$b){ $a 私有成员属性的原值 $b 私有成员属性的新值 function __set($a,$b){ if($pro == 'sex'){ echo '##'; //var_dump($a); //var_dump($b); $this->$a = $b }else{ echo '禁止修改 '; //没有返回值 } } function __isset(){ echo '######'; var_dump($pro); // return isset($this->$pro); } } //实例化对象 $lly = new Person; //检查姓名属性是否设置 非私有 //$result = isset($lly->name); //var_dump($result); ture //外部的 isset 无法检测私有成员属性 返回值为 false '''检查私有属性''' $result = isset($lly->sex); var_dump($result)
魔术方法:__unset
<?php class Person { //成员属性 var $name = '李兰英'; private $sex = '男'; var $age = '38'; //成员方法 function say(){ echo '佛爷吉祥'; } function nn(){ echo '哗啦啦啦啦~'; } function __unset(){ //var_dump($a); if($pro == 'sex'){ unset($this->$pro); } } } //实例化对象 $lly = new Person; //删除一个属性 非私有 ''' unset($lly->name); var_dump($lly);''' //删除一个私有成员属性 unset($lly->sex);; var_dump($lly)
继承特性:
继承格式:
class 类名 extends 父亲名{
书写子类独有的方法和人书写;
}
概念:
特点:
子类继承父类既具备父类中所有的成员属性和方法(私有 private 的除外)
子类继承父类之后可以具有子类独有的属性和方法。
爷爷有的 父亲也有 父亲有的 爷爷不一定有
在继承时,子类允许出现和父亲同名的方法,这种情况不会冲突,而是子类的方法会覆盖父类的方法,这种方法叫重载(重新加载)。
魔术方法可以被子类继承。
如果父类具有构造方法,子类也需要构造方法 ,此时需要在子类中重载父亲的构造方法,并且在构造方法中使用 parent::__construct ()
进行调用父亲的构造方法,构造继承而来的父亲的成员属性。 也可以使用类名::__construct ()
来调用父类的构造方法,不推荐使用。一旦父类名字改变,继承失效。
继承代码的时候不要瞎继承,人类不要继承鸟类。要有一定的逻辑关系。
php继承特点和和其他语言继承的区别:
<?php //继承特性 爷爷有的 父亲也有 父亲有的 爷爷不一定有 //爷爷类 class GrandFather{ //成员属性 var $familyname = '曹'; var $lastName = '操'; private $xifu = '老婆'; //成员方法 //吃饭 function chi { echo '会吃饭'; } function he { echo '会喝水'; } function __construct{ $this->lastName= '天骄'; } } ''' //父亲类 class Father{ //成员属性 var $familyname = '曹'; var $lastName = '操'; var $money = '100'; //成员方法 //吃饭 function chi { echo '会吃饭'; } function he { echo '会喝水'; } function piao { echo '足浴大会员'; } } $father = new Father; var_dump (Father); //但一般不使用复制代码的方式去继承''' //父亲类 class Father extends GrandFather{ var $money = '100'; function piao() { echo '足浴大会员'; } } function __construct{ $this->sex = mt_rand(0,1) ? '男':'女'; //$this->lastName= '天骄'; //调用父亲的构造方法 //GrandFather::__construct //调用父亲的构造方法2 } $father = new Father; var_dump (Father);
关键字/位置 | 类外 | 类内部 | 子类 |
---|---|---|---|
private | x | √ | x |
public | √ | √ | √ |
protected | x | √ | √ |
<?php class libei { //成员属性 protected $fname ='刘'; private $lastname = '备'; public $horse = '的卢'; //方法 private function cry(){ echo '呜呜呜呜呜呜呜~'; } protected function say(){ echo '正在说话中'; } public function zhandou(){ echo '正在战斗中'; } ''' function texvisit(){ echo $lb->horse; echo '<br/>'; echo $lb->lastname; echo '<br/>'; echo $lb->fname; 类的内部可以访问 }''' } //实例化一个刘备对象 $lb = new luibei(); //在类的外部访问成员属性 '''echo $lb->horse; echo '<br/>'; echo $lb->lastname; echo '<br/>'; echo $lb->fname; 只有的卢(public)才可以访问 剩下的无法访问 ''' '''class adou extends luibei{ function texvisit(){ echo $lb->horse; echo '<br/>'; echo $lb->lastname; echo '<br/>'; echo $lb->fname; }; //实例化阿斗对象 $ad = new adou; $ad->texvisit(); 的卢可以 刘可以'''