前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >php学习之类与对象的魔术方法的使用

php学习之类与对象的魔术方法的使用

作者头像
吾爱乐享
发布2019-12-30 17:08:30
5700
发布2019-12-30 17:08:30
举报
文章被收录于专栏:吾爱乐享吾爱乐享吾爱乐享

魔术方法有哪些

  1. __construct:构造方法
  2. __destuct:析构方法
  3. __call:在对象中调用一个不可访问的方法时。__call()会被调用
  4. __callStatic:
  5. __get:调用不可访问的属性
  6. __set:给不可访问的属性赋值或修改值
  7. __isset:
  8. __unset:
  9. __sleep:串行化的时候用,涉及到序列化
  10. __wakeup:反串行化的时候用,涉及到序列化
  11. __toString:
  12. __set_state:
  13. __clone:对象克隆前被调用

说明:

  1. 魔术方法都是系统提供的
  2. 所有的魔术方法,前面都是以__两个下划线
  3. 我们在自定义函数时,不建议已经能用两个_开始
  4. 魔术方法是在满足某个条件时,系统自动调用

访问控制修饰符的基本知识

访问修饰符包括:

  • public:公有,被定义该修饰的成员可以在任何地方被访问
  • protected:受保护的,被定义该修饰符的成员可以被自身及其子类和父类访问
  • private:私有。被定义该修饰符的成员只能被其定义所在的类中访问

访问修饰符既可以修饰成员属性,也可以修饰成员方法

访问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;

} 
//访问protected属性
public function get_age(){
return $this->age;
} 
//访问private属性
public function get_sex(){
return $this->sex;
}
}
//创建对象
$p1 = new Person('张三',23,'男');
//访问各个属性

//访问公共属性public ,则可以直接访问
echo $p1->name;
//访问protected,不可以直接访问,解决方法是编写一个public的成员方法,来操作protected属性
echo $p1->get_age();
//访问private,不可以直接访问,解决方法是编写一个public的成员方法,来操作private属性
echo $p1->get_sex();

魔术方法之   __get函数和__set函数

当开发者去使用不可以访问的属性时,系统就会调用__get方法

不可访问的属性指:

  • 属性不存在
  • 直接访问protected属性
  • 直接访问private属性

当去给不可访问的属性直接赋值时,系统会调用__set方法

案例:

成员属性不可访问或者被私有,希望用对象名->变量名来赋值和取值

<?php 
class Monkey{
public $name;
protected $food;

//构造方法,
public function __construct($name,$food){
$this->name = $name;
$this->food = $food;

}
//魔术方法—__get()
//$monkey_name代表形参,传过来的被私有或者受保护的属性名这里指的是$food
public function __get($monkey_name){
//做一个判断
if(property_exists($this,$monkey_name)){
return $this->$monkey_name;
}else{
return '没有该属性值';
}

}
//魔术方法- __set()

public function __set($monkey_name,$monkey_val){
if(property_exists($this,$monkey_name)){
$this->$monkey_name = $monkey_val;
}else{
return '该属性不存在';
}
}

}

//创建对象
$monkey1 =new Monkey('小白','胡萝卜');
echo $monkey1->name;
echo $monkey1->food;
//修改属性值
$monkey1->name = '程序猿';//公共属性直接可以修改赋值
echo $monkey1->name;
//默认protected的属性赋值时,会调用set方法
$monkey1->food = '夜宵';

$monkey1->food;

魔术方法之 __isset和__unset方法

  1. 当对不可访问的属性进行isset($对象名->属性),empty($对象名->属性)操作时,系统就会调用__isset函数
  2. 当对不可访问的属性进行unset($对象名->属性),系统就会调用__unset()函数

案例:unset($house->name);//Fatal error: Cannot access private property House::$name in D:\wamp64\www\issetunset.php on line 40

直接访问会提示不能调用被私有的属性,此时会自动调用__unset()魔术方法,在魔术方法中执行删除,然在打印,就会被删除掉

<?php

//定义一个房子类House

class House {

//定义三个成员属性,价格Price、地址add、姓名name其中姓名私有private

public $price;

public $add;

private $name;

//定义构造方法

public function __construct ($price,$add,$name){

$this->price = $price;

$this->add = $add;

$this->name =$name;

//魔术方法




}

public function __isset($name1){

//property_exists()判断对象的属性或方法是否存在

if(property_exists($this,$name1)){

echo '存在';

}else{

echo 2;

}




}

//魔术方法—__unset()

public function __unset($name){

//判断成员属性是否存在

if(property_exists($this,$name)){

unset($this->$name);

}else{

echo '不存在';

}

}

}

$house = new House(1000,'陕西西安','张三');

//直接调用name返回的是2,被私有了无法赋值,用isset判断时要想用$对象名->属性名访问,就要使用魔术方法__isset();

 if(isset($house->name)){

echo $house->name;

}else{

echo 2;

}

//add属性是公开的,所以可以直接打印出来值

if(isset($house->add)){

echo $house->add;

}else{

echo 2;

}

//unset()销毁成员属性

unset($house->name);//Fatal error: Cannot access private property House::$name in D:\wamp64\www\issetunset.php on line 40直接访问会提示不能调用被私有的属性,此时会自动调用__unset()魔术方法,在魔术方法中执行删除,然在打印,就会被删除掉

var_dump($house);

?>

魔术方法之__toString

当我们希望将一个对象当作字符串输出时,就会触发__toString魔术方法

魔术方法tostring tostring没有形式参数 debug调试时,需要查看对象信息

案例:

<?php

class Dog{
private $name;
private $age;
private $benling;

//构造方法
public function __construct($name,$age,$benling){
$this->name = $name;
$this->age = $age;
$this->benling = $benling;

}
//魔术方法tostring
//tostring没有形式参数
//debug调试时,需要查看对象信息

public function __toString(){
return '小狗的名字是 '. $this->name . '年龄为 ' . $this->age . '爱好为 ' . $this->benling; 

}

}
$dog = new Dog('藏獒',5 ,'看家');

//直接打印输出会触发toString魔术方法,如果不写会报错

echo $dog;

?>

魔术方法之__clone

当我们需要将一个对象完全的复制一份,保证两个对象的属性和属性值一样,但他们的数据空间是独立的,则可以使用对象克隆

说明:

  1. 当我们$对象1 = $对象2时会触发__clone方法
  2. 如果我们希望克隆,修改某个属性则在__clone方法中去修改即可
  3. 如果我们希望阻止克隆,只需要将__clone魔术方法申明为private即可

案例:

<?php

class Sheep{
public $name;
protected $food;
public function __construct($name,$food){
$this->name = $name;
$this->food = $food;

}
//__clone 魔术方法
//如果希望阻止克隆,则将__clone 申明为private
public function __clone(){
//在克隆一个对象时,可以在这个__clone 函数中去修改某个属性,如果有必要的话
echo '复制一个';

}

}
$sheep1 = new Sheep('喜羊羊', '灰太狼');
//对象克隆会触发__clone的魔术方法,克隆只是值拷贝
$sheep2 = clone $sheep1;
if($sheep1==$sheep2){
echo '相等';
}
if($sheep1===$sheep2){
echo '全等';
}

魔术方法之__call函数

当我们调用要给不可访问的成员方法时,__call魔术方法就会被调用(不可访问即该成员方法不存在,成员访问被protected和private修饰)

__call魔术方法中,有两个参数

  1. 函数名:$mathod
  2. 参数 类型数组:$parameters

案例:

在类的外部调用不可访问的成员方法

<?php
header('content-type:text/html; charset=utf-8');
class Sheep{
public $name;
protected $food;
//构造方法
public function __construct($name,$food){
$this->name = $name;
$this->food = $food;
}
//展示对象都有哪些信息
public function show(){
echo '<br>小羊的名字是 ' . $this->name;
foreach($this->food as $food){
echo '食物是 ' . $food;
}
}

//定义一个受保护的方法
protected function hoddy($hoddy1,$hoddy2){
echo '<br>喜羊羊的第一个爱好是 ' . $hoddy1;
echo '<br>喜羊羊的第二个爱好是 ' . $hoddy2;
}
//编写一个__call魔术方法,__call魔术方法会接收两个参数
/*
@param $mathod_name 函数名
@param $parameters 就是参数,类型为array
*/
public function __call($method_name,$parameters){
//判断$this中是否有$method_name函数,
if(method_exists($this,$method_name)){
return $this->$method_name($parameters[0],$parameters[1]);
}
else{
echo '没调用该函数';
} 

}
}
$sheep = new Sheep('喜羊羊' , array('青草','灰太狼'));
$sheep->show();
//当我们直接调用受保护的方法时,会触发__call魔术方法
$sheep->hoddy('玩','打灰太狼');

?>

实战:

有一个cat类,有年龄和名字两个属性,要求这两个属性全部都是public,cat类有一个方法jisuan($n1,$n2,$oper)可以计算+-*/,该方法是私有的,在类的外部$对象名->play(‘jisuan’,$n1,$n2,$oper)得到结果,该方法在类中没有定义

要求play是固定的,如果没有按规定写,则给出相应的错误提示

<?php
header('content-type:text/html; charset=utf-8');
class Cat{

public $name;
public $age;
//构造方法
public function __construct($name,$age){
$this->name = $name;
$this->age = $age;
}

//定义一个jisuan方法
private function jiSuan($n1,$n2 ,$oper){
$res = 0;
//判断符号并计算
switch($oper){
case '+':
$res = $n1 + $n2;
break;
case '-':
$res = $n1 - $n2;
break;case '*':
$res = $n1 * $n2;
break;case '/':
$res = $n1 / $n2;
break;
default:
echo '输入的符号错误,请重新输入';
}
return $res;

}
//编写要给__call魔术方法
public function __call($method_name,$parameters){
//判断是否通过play方法调用
if($method_name == 'play'){
//判断jisuan()方法是否存在
if(method_exists($this,$parameters[0])){
return $this->$parameters[0]($parameters[1],$parameters[2],$parameters[3]);
}else{
echo '你调用的'.$patameters[0].'不存在';
}
}else{
echo '你调用的方式有问题';
}
}
}
$cat = new Cat('tom',23);
echo $cat->play('jiSuan',1,2,'*');
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2018-11-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 魔术方法有哪些
    • 说明:
      • 访问修饰符包括:
  • 访问控制修饰符的基本知识
  • 魔术方法之   __get函数和__set函数
  • 魔术方法之 __isset和__unset方法
  • 魔术方法之__toString
  • 魔术方法之__clone
  • 魔术方法之__call函数
    • 实战:
    相关产品与服务
    文件存储
    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档