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

原标题:php学习之类与对象的魔术方法的使用

魔术方法有哪些

__construct:构造方法

__destuct:析构方法

__call:在对象中调用一个不可访问的方法时。__call()会被调用

__callStatic:

__get:调用不可访问的属性

__set:给不可访问的属性赋值或修改值

__isset:

__unset:

__sleep:串行化的时候用,涉及到序列化

__wakeup:反串行化的时候用,涉及到序列化

__toString:

__set_state:

__clone:对象克隆前被调用

说明:

魔术方法都是系统提供的

所有的魔术方法,前面都是以__两个下划线

我们在自定义函数时,不建议已经能用两个_开始

魔术方法是在满足某个条件时,系统自动调用

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

访问修饰符包括:

public:公有,被定义该修饰的成员可以在任何地方被访问

protected:受保护的,被定义该修饰符的成员可以被自身及其子类和父类访问

private:私有。被定义该修饰符的成员只能被其定义所在的类中访问

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

访问protected,private不可以直接访问,解决方法是编写一个public的成员方法,来操作protected和private属性

<?phpclass 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代表形参,传过来的被私有或者受保护的属性名这里指的是$foodpublic 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;

7bcd5a9f2d30051f0045470ecc908540.png

魔术方法之 __isset和__unset方法

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

当对不可访问的属性进行unset($对象名->属性),系统就会调用__unset()函数

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

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

<?php //定义一个房子类Houseclass House {//定义三个成员属性,价格Price、地址add、姓名name其中姓名私有privatepublic $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);?>

abe8eabdb346cab0b1f22e1d5a7f54f5.png

魔术方法之__toString

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

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

案例:

<?phpclass 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 = $对象2时会触发__clone方法

如果我们希望克隆,修改某个属性则在__clone方法中去修改即可

如果我们希望阻止克隆,只需要将__clone魔术方法申明为private即可

案例:

<?phpclass Sheep{public $name;protected $food;public function __construct($name,$food){$this->name = $name;$this->food = $food;}//__clone 魔术方法//如果希望阻止克隆,则将__clone 申明为privatepublic function __clone(){//在克隆一个对象时,可以在这个__clone 函数中去修改某个属性,如果有必要的话echo '复制一个';}}$sheep1 = new Sheep('喜羊羊', '灰太狼');//对象克隆会触发__clone的魔术方法,克隆只是值拷贝$sheep2 = clone $sheep1;if($sheep1==$sheep2){echo '相等';}if($sheep1===$sheep2){echo '全等';}

352ecec3a4f34f5b1939a31c945338e1.png

魔术方法之__call函数

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

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

函数名:$mathod

参数 类型数组:$parameters

案例:

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

<?phpheader ('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 '
小羊的名字是 ' . $this->name;foreach($this->food as $food){echo '食物是 ' . $food;}}//定义一个受保护的方法protected function hoddy($hoddy1,$hoddy2){echo '
喜羊羊的第一个爱好是 ' . $hoddy1;echo '
喜羊羊的第二个爱好是 ' . $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('玩','打灰太狼');?>

efdd09a723bf1cb5ada6af723c153d3e.png

实战:

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

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

<?phpheader ('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,'*');

责任编辑:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/526000.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

oracle 执行sql,Oracle动态执行SQL

方式1CREATE OR REPLACE PROCEDURE demo(salary IN NUMBER) AScursor_name INTEGER;rows_processed INTEGER;BEGINcursor_name : dbms_sql.open_cursor;dbms_sql.parse(cursor_name, DELETE FROM emp WHERE sal > :x,dbms_sql);dbms_sql.bind_variable(cursor_name, :x, sal…

oracle 满足条件取第一行,sql – 如何只选择满足条件的第一行?

您可以使用分析查询&#xff1a;select *from (select p.*, v.*,row_number() over (partition by p.id order by v.userid) as rnfrom prmprofile pjoin user v on v.profile p.idwhere p.language 0and v.userid like %TEST%)where rn 1;内部查询获取所有数据(但使用*不理…

Linux怎么把目录设置群组,linux设置目录和文件使用权限

ext2fs文件系统中的目录及文件&#xff0c;可依实际需要来设置可读取、可写入与可执行等权限。以下我们就来了解文件和目录的权限设置。ext2fs文件系统中的目录及文件&#xff0c;可依实际需要来设置可读取、可写入与可执行等权限。以下我们就来了解文件和目录的权限设置&#…

linux异常关机内存,linux关机及问题解决

一般linux关机会用到的命令就是shutdown命令shutdown命令在执行的时候会自动去调用sync这个工具&#xff0c;这个工具的作用是把内存里面的东西写入硬盘。不过为了安全&#xff0c;一般我们在执行shutdown命令的时候都用去执行几次sync这个命令。shutdown -k noticesshutdown -…

linux查看redis内存,Linux查看redis占用内存的方法

redis-cliauth 密码info# Memoryused_memory:13490096 //数据占用了多少内存(字节)used_memory_human:12.87M //数据占用了多少内存(带单位的&#xff0c;可读性好)used_memory_rss:13490096 //redis占用了多少内存used_memory_peak:15301192 //占用内存的峰值(字节)used_memor…

linux子进程父进程例子,linux 子进程访问父进程

问题分析ECS Linux 系统下 Apache 的默认工作模式是 prefork MPM&#xff0c;使用多个子进程&#xff0c;每个子进程只有一个线程。每个进程在某个确定的时间只能维持一个连接&#xff0c;效率高&#xff0c;但内存占用量比较大。如果不做调整&#xff0c;访问量增大可能造成 A…

linux 查看进程的信号,Linux 进程信号查看与控制

Linux 进程信号查看与控制1) SIGHUP 本信号在用户终端连接 (正常或非正常) 结束时发出通常是在终端的控制进程结束时通知同一 session 内的各个作业这时它们与控制终端不再关联?2) SIGINT 程序终止 (interrupt) 信号在用户键入 INTR 字符 (通常是 Ctrl-C) 时发出?3) SIGQUIT …

linux查看发起ddos攻击的ip,在Linux上使用netstat命令查证DDOS攻击的方法

导读DOS攻击或者DDOS攻击是试图让机器或者网络资源不可用的攻击。这种攻击的攻击目标网站或者服务通常是托管在高防服务器比如银行&#xff0c;信用卡支付网管&#xff0c;甚至根域名服务器。服务器出现缓慢的状况可能由很多事情导致&#xff0c;比如错误的配置&#xff0c;脚本…

linux还原windows,双系统如何删除Linux,恢复Windows从  MBR引导启动?

双系统如何删除Linux&#xff0c;恢复Windows从MBR引导启动&#xff1f;现在愿意尝试Linux的人越来越多了。通常&#xff0c;如果一台电脑里已经装有了Windows&#xff0c;再装Linux&#xff0c;安装时&#xff0c;Linux的grub引导程 序就会覆盖掉保存在MBR当中的原来的Windows…

linux ftp下载函数函数,FTP下载的函数

最近写的一个到指定FTP下载服务器上下载的函数&#xff0c;主要用到类有CInternetSession&#xff0c;CFtpConnection具体内容看代码吧&#xff0c;这个不能的!虽然很简单&#xff0c;不值得往外写&#xff0c;但我想收藏起来留着以后用也是很有意义的。/*********************…

linux应用程序逆向,Linux下查看并下载命令源码包(根据命令/应用程序逆向获取并且安装其所属源码包)...

使用linux的过程中&#xff0c;我们会熟悉各种命令&#xff0c;偶尔我们不禁会问&#xff0c;这些命令是怎么实现的&#xff0c;学习他们其实是学习linux高级系统编程很快捷的方法。这些命令的源码肯定是存放在相应的包里面&#xff0c;但是是哪些包呢&#xff1f;发行版的包管…

linux路由信息预览为空,route - 显示并设置Linux中静态路由表

补充说明route命令 用来显示并设置Linux内核中的网络路由表&#xff0c;route命令设置的路由主要是静态路由。要实现两个不同的子网之间的通信&#xff0c;需要一台连接两个网络的路由器&#xff0c;或者同时位于两个网络的网关来实现。在Linux系统中设置路由通常是为了解决以下…

linux maven自动构建,Centos7.3+Jenkins+Git+Maven 自动化构建部署项目

第一步 禁止 SELINUX 访问控制修改配置之前先备份(良好习惯)sudo cp /etc/selinux/config /etc/selinux/config.bak备份后&#xff0c;修改selinux配置sudo vi /etc/selinux/config将SELINUXenforcing改为SELINUXdisabled第二步 卸载系统自带的OpenJDK以及相关的java文件 安装J…

linux windows变色龙,体验开源变色龙SUSE Linux Enterprise Server 11

体验开源变色龙SUSE Linux Enterprise Server 11SUSE Linux Enterprise Server 11主要针对的是企业用户&#xff0c;SUSE产品分为SUSE Linux Enterprise Desktop(SLED)和SUSE Linux Enterprise Server(SLES)两个版本。笔者测试的版本为Server版本&#xff0c;主要面向SMB甚至是…

c语言简单编程题模板,C语言编程题,比较简单

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼#include #include int main(){int mark0,falut0;float answer0,k1;char m;int n;int i1;float timu(char q);float re(float a,float b,char h);printf("please input the number of the question you want to answer and th…

c语言建立顺序表 存储并输出,请教数据结构课程中怎么建立顺序表,显示,输出,从头到尾详细点最好加讲解,希望大家能帮这个小忙...

#include#define MAXSIZE 20typedef int ElemType;typedef struct{ElemType elem[MAXSIZE];int length;}SqList;//顺序表结构定义void InitList(SqList &L){//初始化函数//操作结果&#xff1a;构造一个空在顺序线性表 L.length0;return;}void ClearList(SqList &L){//…

杭州师范大学c语言程序设计机试,2016年杭州师范大学杭州国际服务工程学院程序设计基础考研复试题库...

一、选择题1&#xff0e; C 语言源程序名的后缀是( )A.C B.exe C.obj D.cp 答:A 【解析】C 语言源程序名的后缀为.C2&#xff0e; 以下选项中不合法的标识符是A.printB.FORD._00 答:C【解析】标识符是由若干个字符组成的字符序列&#xff0c;用来命名程序的一些实体。语法规则为…

在c语言中关于静态变量的说法正确的有,关于static变量,请选择下面所有说法正确的内容。...

static表示“全局”或者“静态”的意思&#xff0c;用来修饰成员变量和成员方法&#xff0c;也可以形成静态static代码块&#xff0c;但是Java语言中没有全局变量的概念。被static修饰的成员变量和成员方法独立于该类的任何对象。也就是说&#xff0c;它不依赖类特定的实例&…

c语言数组下标越界检查程序,数组下标越界

已结贴√问题点数&#xff1a;20 回复次数&#xff1a;11数组下标越界题目是一个有10个元素的数组&#xff0c;存有10个考生的分数&#xff0c;写5个函数&#xff0c;分别计算总分&#xff0c;最高分&#xff0c;最低分&#xff0c;平均分&#xff0c;分数升序排列。我写了5函数…

c语言标准整形,C语言整形数值范围问题

有符号二进制数的表示是这样的&#xff1a;如果计算机的字长为n位&#xff0c;n位二进制数的最高位为符号位。其余n-1位为数值位&#xff0c;采用补码表示法时&#xff0c;可表示的数X的范围是 -2的(n-1)次幂 < X < 2的(n-1)次幂-1。如果字长是16位&#xff0c;补码表示的…