启东的个人博客 - 面向对象
type: channel
link: https://echo.solo90.com/tag/%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/
items: JavaScript 面向对象(三) 高级篇
items: JavaScript 面向对象(二) 案例篇
items: JavaScript 面向对象(一) 基础篇
items: php面向对象编程（十五）异常捕获和处理
items: php面向对象编程（十四）反射机制和动态代理
items: php面向对象编程（十三）三大特性之多态
items: php面向对象编程（十二）interface接口
items: php面向对象编程（十）魔术方法和自动引入类机制
items: php面向对象编程（九）延迟绑定static
items: php面向对象编程（八）常量关键字const、和traits

JavaScript 面向对象(三) 高级篇
type: item
date: 2018-04-24T08:52:00+00:00
description: json方式的面向对象首先要知道，js中出现的东西都能够放到json中。关于json数据格式这里推荐一篇博客：JSON 数据格式先看下json创建的简单对象：相比基础篇中的构造函数、原型等的创建方式，json方式简单方便；但是缺点很明显，如果想创建多个对象，那么会产生大量重复代码，不可取。JSON方式适用于只创建一个对象的情况，代码简介又优雅。 JSON在JS面向对象的应用中，主要的一个作用就是命名空间：如果有大量常用的js函数，利用json，我们可以将同一类函数放在一个“类”里，类似于java那样，这样我们就能很好的管理和查找使用这些js函数，看下面的例子就很好理解了。 面向对象的继承先举个简单的例子来说一下JS中的继承，Student <extends> Person；在js中，通过call来调用父类的构造方法继承父类的属性(第33行)，通过原型来继承父类的方法(第39行)。注意：先调用父类构造函数，再添加自己的属性；先继承父类的方法，再添加自己的方法。这里解释下为什么调用Person.call(this, name, sex)就相当于是在调用父类的构造方法：先问一下这个call中的this是谁？这里指向对象student吧。所以，在子构造函数中调用Person.call()时，那么构造函数Person里的两行代码this.name=name, this.sex=sex中this就是代表student了，所以这两行代码相当于是在为student添加name和sex属性。但是，下面的通过原型来继承父类的方法，即Student.prototype = Person.prototype，是有问题的，这种方式将影响父类(继承是不能影响父类的)，此时Person的原型中有了个showMajor方法(第50行)，为什么呢？先思考下，下面解释。 第50行弹出的信息：为了解释为什么通过Student.prototype = Person.prototype来继承父类的方法会影响父类，下面举一个数组的例子，一看就知道怎么回事了。为什么arr1和arr2弹出来的一样呢？第15、16行显示arr1和arr2是一个对象。对象！应该很清楚了吧，arr1和arr2都是指向这个数组对象的一个引用，所以改变arr2时，arr1也变了。 其实我们主要是想获得arr1数组的一个副本，怎么做才能不改变arr1呢，看下面： 同样的，我们也可以通过这种方式为继承的子类添加父类原型中的方法，而又不影响父类(38-41行)： 第53行弹出信息：Person中没有showMajor方法了。/** * 拖拽 * @param {Object} id div的id */ function Drag(id){ this.oBox = document.getElementById(id); this.disX = 0; this.disY = 0; var _this = this; this.oBox.onmousedown = function(){ _this.fnDown(); } } //鼠标按下 Drag.prototype.fnDown = function(ev){ var oEvent = ev || event; this.disX = oEvent.clientX - this.oBox.offsetLeft; this.disY = oEvent.clientY - this.oBox.offsetTop; var _this = this; document.onmousemove = function(){ _this.fnMove(); }; document.onmouseup = function(){ _this.fnUp(); }; } //鼠标移动 Drag.prototype.fnMove = function(ev){ var oEvent= ev || event; this.oBox.style.left = oEvent.clientX - this.disX + 'px'; this.oBox.style.top = oEvent.clientY - this.disY + 'px'; } //鼠标抬起 Drag.prototype.fnUp = function(){ document.onmousemove = null; document.onmouseup = null; }drag.html 拖拽 效果：可以看到红色和蓝色的都出边界了，但我们又不想去修改代码，那我们怎么做？学过java的应该都知道可以写一个子类来做一些更加具体的操作，又保留了父类的功能，就是继承。DragLimit.js：DragLimit继承自D…

JavaScript 面向对象(二) 案例篇
type: item
date: 2018-04-23T13:50:00+00:00
description: 案例——面向对象的选项卡把面向过程的程序一步步改成面向对象的形式，使其能够更加的通用(但是通用的东西，一般会比较臃肿)。下面是一个简单的选项卡，也是我们常见的面向过程的创建形式。 选项卡 GTA5、孤岛惊魂 澳大利亚、西藏 暗里着迷、一生有你 效果：图下面来一步步改成面向对象的形式。1.首先将嵌套的函数拿到window.onload外面，不能有函数嵌套，可以有全局变量。如下：所有的改写最终效果都不变。 选项卡 GTA5、孤岛惊魂 澳大利亚、西藏 暗里着迷、一生有你 2.将全局的变量变为对象的属性，全局的函数变为对象的方法；将window.onload里的代码提取到一个构造函数里面，在window.onload里创建对象即可；(下面的代码执行起来是有问题的)。这里必须注意：在构造函数Tab里的this跟之前this所代表的是不同的(此处是通过new来创建对象的)；在上面的示例中，this指的是调用者；在构造函数里，this指向的是var tab = new Tab() ，即tab这个对象，注意是对象。说一下这段代码的问题：我们在Tab的原型上添加clickBtn方法后，clickBtn方法里的this本应该是指向var tab = new Tab()的，但是我们在第44行将clickBtn添加给了this.tabBtn[i]，即input按钮，clickBtn的所属由Tab对象变成了input按钮(第49行)。clickBtn的所属变成input按钮后，那么clickBtn里的this指向按钮，那再来看clickBtn里的代码，this.tabBtn、this.tabDiv，input按钮里有这两个属性吗？没有，所以会出错！ 选项卡 GTA5、孤岛惊魂 澳大利亚、西藏 暗里着迷、一生有你 将clickBtn赋给input按钮后，方法内的this也指向了input按钮：执行第49行代码的效果图3.将clickBtn的调用放在一个函数里，这样就不会改变clickBtn的所属了。看第41-47行，注意在function里需要用到外部保存的变量_this。再看第52行，此时弹出的是一个Object，说明clickBtn的所属关系没变，还是Tab对象。但是还有另一个问题，此时clickBtn里的this指向对象，那么看第57、58行中this.className、this.index，此处的this指的是tab对象，那么对象中有这两个属性吗？没有，还会出错！ 选项卡 GTA5、孤岛惊魂 澳大利亚、西藏 暗里着迷、一生有你 4. 以参数的形式将点击的按钮传入clickBtn中，看第44行代码，以及54,55行代码 选项卡 GTA5、孤岛惊魂 澳大利亚、西藏 暗里着迷、一生有你 5.最终版 —— 将代码提取到一个单独的js文件中，在用的时候引入即可。一般花大时间去写一个面向对象的程序，就是为了能够复用，以及方便的使用。tab.js/** * 选项卡 * @param {Object} id 选项卡id */ function Tab(id){ var tabBox = document.getElementById(id); this.tabBtn = tabBox.getElementsByTagName('input'); this.tabDiv = tabBox.getElementsByTagName('div'); for(var i=0;i<this.tabBtn.length;i++){ this.tabBtn[i].index = i; var _this = this; this.tabBtn[i].onclick = function(){ _this.clickBtn(this); }; } }; /** * 为Tab原型添加点击选项卡方法 * @param {Object} btn 点击的按钮 */ Tab.prototype.clickBtn = function(btn){ for(var j=0;j<this.tabBtn.length;j++){ this.tabBtn[j].className=''; this.tabDiv[j].style.display='none'; } btn.className='active'; this.tabDiv[btn.index].style.display='block'; };使用：tab.html 可以看到使用的时候，就可以很简单的创建两个选项卡出来了。效果： ![图][3] 看的有点晕吧，一定要好好理解JS面向对象中的this。js中面向对象大部分时候出问题就是出在this的处理上，需要注意。 面向过程：简洁、美观、容易维护； 面向对象：容易出错、混乱、难以维护…

JavaScript 面向对象(一) 基础篇
type: item
date: 2018-04-22T13:36:00+00:00
description: 面向对象(Java面向对象亦是如此)1.对象：对象是一个整体，对外提供一些操作。2.面向对象：使用对象时，只关注对象提供的功能，不关注其内部细节。比如电脑——有鼠标、键盘，我们只需要知道怎么使用鼠标，敲打键盘即可，不必知道为何点击鼠标可以选中、敲打键盘是如何输入文字以及屏幕是如何显示文字的。总之我们没必要知道其具体工作细节，只需知道如何使用其提供的功能即可，这就是面向对象。3.JS的对象组成：方法 和 属性在JS中，有函数、方法、事件处理函数、构造函数，其实这四个都是函数，只是作用不同。函数是独立的存在，方法属于一个对象，事件处理函数用来处理一个事件，构造函数用来构造对象。首先通过常用的数组来认识下JS的对象： 4.认识下JS中的this以及全局对象window 此处的show()函数为一个全局函数，调用show()，alert(this)弹出来的是window对象，说明全局函数属于window。上面定义的show()等于为window添加一个方法，全局的函数和变量都是属于window的，上面的定义等价于下面。 同样的我们也可以根据自己的需求为其它的对象添加方法，比如显示数组：但是我们不能在系统对象中随意附加方法和属性，否则可能会覆盖已有方法、属性。 从上面的例子也可以看出来，this即表示当前函数的调用者是谁，但是在一种情况下不是的，就是使用new 来创建对象时，this并不是指向调用者的，在后面会有说明。window是全局对象，可以看下属于window的全局属性和全局方法：JS中自定义对象，逐步分析JS中的创建对象1.通过Object创建简单对象：这种方式有一个非常大的弊端，就是如果我有多个人怎么办，每次都要新建一个对象，然后添加属性、方法，这种方式是一次性的，会产生大量重复代码，这是不可取的。 2.用工厂方式来构造对象：工厂简单来说就是投入原料、加工、出厂。通过构造函数来生成对象，将重复的代码提取到一个函数里面，避免像第一种方式写大量重复的代码。这样我们在需要这个对象的时候，就可以简单地创建出来了。 但是，这种方式有两个缺点：①一般我们创建对象是通过new来创建，比如new Date()，这里使用的是方法创建。使用new来创建可以简化一些代码，也带来一些新的特性。②每个对象都有一套自己的方法，浪费资源(虽然对于现在的计算机来说不算什么，但我们尽量将设计做到最好就行了)。这里为什么说每个对象都有自己的一套方法呢，是因为创建function()的时候其本质是通过new Function()来创建的，会诞生一个新的函数对象，所以每个对象的方法是不一样的，这样就存在资源浪费的问题了。看第25行代码。 使用new 来创建JS对象 弹出信息显示this即是一个Object(第13行代码)。在方法调用前使用new来创建，function内的this会指向一个新创建的空白对象，而不是指向方法调用者，而且会自动返回该对象。但是这种方式只解决了第一个问题，每个对象还是有自己的一套方法(第35行代码)。4.在function原型(prototype)上进行扩展原型添加的方法不会有多个副本，不会浪费资源，所有的对象只有一套方法(看第29行代码)。 至于为什么是用的一套方法呢，看第31行代码：因为所有的方法都等于原型上的方法。 通过prototype我们还可以很方便的扩展系统对象，按照自己的需求来扩展，而且又能适用于所有地方，又不会浪费资源。如下面对Array进行扩展，求数组和的方法。 原文地址：https://www.cnblogs.com/chiangchou/p/js-oop1.html

php面向对象编程（十五）异常捕获和处理
type: item
date: 2018-01-19T06:47:00+00:00
description: php中的异常扩展PHP内置的异常处理类；可以通过实例化Exception类或者它的子类来创建一个异常实例。Exception::__construct — 异常构造函数Exception::getMessage — 获取异常消息内容Exception::getPrevious — 返回异常链中的前一个异常Exception::getCode — 获取异常代码Exception::getFile — 创建异常时的程序文件名称Exception::getLine — 获取创建的异常所在文件中的行号Exception::getTrace — 获取异常追踪信息Exception::getTraceAsString — 获取字符串类型的异常追踪信息Exception::__toString — 将异常对象转换为字符串Exception::__clone — 异常克隆内置异常子类Exception是所有异常类的基类、下面两个直属子类LogicException 逻辑处理异常类,和RuntimeException 运行时异常类。php中异常处理异常处理功能提供了处理程序运行时出现的错误或异常情况的方法。PHP5提供了一种新的面向对象的错误处理方法。使用检测(try）、抛出(throw)和捕获(catch)异常。try 使用异常的函数应该位于”try”代码块内。如果没有出发异常,则代码将照常继续执行。如果异常被出发，会抛出一个异常。throw 这里规定如何出发异常，每一个“throw”,必须对应至少一个”catch”.catch “catch”代码块会捕获异常，并创建一个包含异常信息的对象。一个 try 至少要有一个与之对应catch。定义个多个catch可以捕获不同的对象.php会按这些catch被定义的顺序执行，知道完成最后一个为止。php异常处理语句$e = new Exception('我是错误',2); echo "错误信息：",$e->getMessage()," "; echo "错误行号：",$e->getLine(); throw $e; //如果抛出异常不捕获 将会报错Fatal error: Uncaught Exceptio<?php //正确语法 class A{ public function __construct(){ throw new Exception('错误信息'); } } try{ $a=new A(); echo "没有异常、我会执行"; }catch(Exception $e){ echo '在文件',$e->getFile(),'中的第',$e->getLine(),'行，中产生异常信息:',$e->getMessage(); }多个catch捕获不同的异常<?php class A{ public function __construct(){ $i=mt_rand(0,5); if($i>2){ throw new OutOfBoundsException('这是一个异常错误',2); }else{ throw new OutOfBoundsException('这是数组越界异常',3); } } } try{ $a=new A(); echo "没有异常、我会执行"; }catch(OutOfBoundsException $e){ echo '在文件',$e->getFile(),'中的第',$e->getLine(),'行，产生异常信息:',$e->getMessage(); }catch(Exception $e){ echo "这是普通异常：",$e->getMessage(); }嵌套try{}catch(){}异常<?php class A{ public function __construct(){ $i=mt_rand(0,10); if($i>2 && $i<5){ throw new OutOfBoundsException('这是一个异常错误',2); }elseif($i<2){ throw new OutOfBoundsException('这是数组越界异常',3); } } } try{ $a=new A(); echo "没有异常、我会执行 "; try{ throw new RangeException('这是新的异常',5); }catch (Exception $ee){ echo $ee->getMessage(); } }catch(OutOfBoundsException $e){ echo '在文件',$e->getFile(),'中的第',$e->getLine(),'行，产生异常信息:',$e->getMessage(); }catch…

php面向对象编程（十四）反射机制和动态代理
type: item
date: 2018-01-19T05:22:00+00:00
description: Reflection反射机制php5添加了一项新的功能:Reflection。这个功能使得程序员可以reflection class,interface,function,method …..。通过PHP代码,就可以得到某类/方法等的所有信息，并且可以和它交互。反射类|可得到的信息:-: | :-:ReflectionFunction()| 函数定义所在的文件以及起始位置等。|ReflectionClass() | 常量/属性/方法/命名空间/类是否为flnal或者abstract等。 |ReflectionMethod()| 方法修饰类型/方法名/方法注释等。|使用方法ReflectionFunction<?php /** * 测试函数 * @author 启东 */ function test(){ echo "我是一个测试函数 "; } test(); $ref_fun = new ReflectionFunction('test');//反射函数类 echo $ref_fun->getDocComment()," ";//函数注释 如果new的是类 使用时类注释 //如果是方法 就是获取方法注释 echo "定义的所在文件名：",$ref_fun->getFileName()," ";//函数定义文件 echo "代码开始行".$ref_fun->getStartLine()." ";//开始行 echo "代码结束行".$ref_fun->getEndLine()." ";//结束行 try { new ReflectionFunction("test1"); }catch(ReflectionException $e){ echo $e->getMessage()," "; };ReflectionClass<?php class A{ function t1(){ echo "我是一个不带参数的方法 "; } function t2($str){ echo "我是一个带一个参数的方法t2,参数是：",$str," "; } private function t3(){ } static function t4(){ echo "我是一个静态方法 "; } } $a=new A(); $ref_cls= new ReflectionClass('A');//参数可以是类名，也可以是类的一个实例 //获取类中的所有方法 $class_all_method=$ref_cls->getMethods();//获取这个类的所有方法 var_dump($class_all_method); /** F:\Work\test\test.php:21: array (size=4) 0 => object(ReflectionMethod)[3] public 'name' => string 't1' (length=2) public 'class' => string 'A' (length=1) 1 => object(ReflectionMethod)[4] public 'name' => string 't2' (length=2) public 'class' => string 'A' (length=1) 2 => object(ReflectionMethod)[5] public 'name' => string 't3' (length=2) public 'class' => string 'A' (length=1) 3 => object(ReflectionMethod)[6] public 'name' => string 't4' (length=2) public 'class' => string 'A' (length=1) */ //判断类中是否有某个方法 hasMethod 返回布尔值 var_dump($ref_cls->hasMethod('t1')); //true var_dump($ref_cls->hasMethod('tt'));//false //判断方法的修饰符 public protected private static //判断方式:is+修饰符 返回布尔值。 //判断之前获取类中的方法 $ref_method=$ref_cls->getMethod('t1'); var_dump($ref_method->isPublic());//判断是否是公开方法ReflectionMethod<?php class A{ function t1(){ echo "我是一个不带参数的方法 "; } function t2($str){ echo "我是一个带一个参数的…

php面向对象编程（十三）三大特性之多态
type: item
date: 2018-01-19T03:48:00+00:00
description: 什么是多态？多态按字面上意思理解就是”多种形状”。可以理解为多种表现形式，即“一个对外接口(方法)，多个内部实现”。在面向对象的理论中，多态性的一般定义为：同一个操作(函数)做用于不同的类的实例（那电脑的USB接口举例、你插U盘是读数据、你插音箱是放音乐），将产生不同的执行结果。也即不同类的对象收到相同的消息时，将得到不同的结果。流程控制实现多态//流程控制实现多态 class Light{ public function show($type=0){ switch($type){ case 0: echo "灯光是红色~ "; break; case 1: echo "灯光是绿色~ "; break; case 2: echo "灯光是蓝色~ "; break; default: echo "随机颜色~ "; break; } } } class User{ function openLight($type=0){ $light=new Light(); $light->show($type); } } $list=new User(); $list->openLight(0); 继承方式实现多态<?php //继承方式实现多态 class Light{ //也可把他设置为 abstract public function show(){ echo "灯光是随机颜色~~ "; } } class BlueLight extends Light { function show(){ echo "灯光颜色是蓝色~~ "; } } class GreenLight extends Light { function show(){ echo "灯光颜色是绿色~~ "; } } class User{ function openLight(Light $obj){ $obj->show(); } } $list=new User(); $light=new Light(); $list->openLight($light); $BlueLight= new BlueLight(); $list->openLight($BlueLight); $GreenLight= new GreenLight(); $list->openLight($GreenLight);接口方式实现多态<?php //接口方式实现多态 interface Light{ //也可把他设置为 abstract public function show(); } class BlueLight implements Light { function show(){ echo "灯光颜色是蓝色~~ "; } } class GreenLight implements Light { function show(){ echo "灯光颜色是绿色~~ "; } } class User{ function openLight(Light $obj){ $obj->show(); } } $list=new User(); $BlueLight= new BlueLight(); $list->openLight($BlueLight); $GreenLight= new GreenLight(); $list->openLight($GreenLight);

php面向对象编程（十二）interface接口
type: item
date: 2018-01-19T02:24:00+00:00
description: PHP中的接口php与大多数面向对象编程语言一样，不支持多重继承，也就是说每个类只能继承一个父类。为了解决这个问题，PHP引入了接口，接口的思想是指定了一个实现了该接口的类必须实现的一系列方法。定义：接口(interface)是抽象方法和静态常量定义的集合。在PHP中，声明接口语法类似声明类，只不过使用关键词interface,interface 接口名{….}规范：接口是一种特殊的抽象类，这种抽象类中只包含抽象方法和静态常量。在接口中的抽象方法只能是public的，默认也是public权限。abstract和final修饰符也不能修饰接口中的抽象方法。<?php interface User{ //public $name 用访问控制修饰符的属性 是报错的 const GROUP =12; //抽象方法是不能有方法体 public function t(); //没有public修饰的方法默认为public }接口的实现和继承接口的实现使用implements来实现以个接口。一个类可以实现多个接口。只要使用逗号(,)将多个接口连接起来就可以。<?php interface User{ function getName(); function setName(); } interface Demo{ function Demo1(); } class Person implements User{ private $name; function getName(){ echo "My name is",$this->name," "; } function setName($name=''){//这里必须的有一个默认值 $this->name = $name; } } //实现继承多个接口 class Stu implements User,Demo{ private $name; function getName(){ echo "My name is",$this->name," "; } function setName($name=''){//这里必须的有一个默认值 $this->name = $name; } function Demo1(){ echo "Demo接口中的demo1方法"; } } $lisi= new Person(); $lisi->setName('李四'); $lisi->getName(); $zhangsan= new stu(); $zhangsan ->setName('张三'); $zhangsan->getName(); $zhangsan->demo1();一个类可以继承类并实现接口<?php interface User{ function getName(); function setName(); } class AdminUser{ public function pubNews(){ echo "管理员发布新闻功能 "; } } class CommonUser extends AdminUser implements User{ private $name; function getName(){ echo "my name is ",$this->name," "; } function setName($name=""){//实现接口的方法如果传变量必须给一个默认值 $this->name=$name; } public function Age($age){ echo "我的年龄是:".$age; } } $lisi = new CommonUser(); $lisi->setName('lisi'); $lisi->getName(); $lisi->age(25);接口的继承一个接口可以继承自另外的接口。要注意只有接口和接口之间使用继承关键字extends。一个接口继承其它接口时候，直接继承父接口的静态常量属性和抽象方法。类实现接口必须实现其抽象方法，使用实现关键字implements。php中的类是单继承，但是接口很特殊。一个接口可以继承自多个接口。抽象类实现接口，可以不实现其中的抽象方法，而将抽象方法的实现交付给具体能被实例化的类去处理。<?php interface User{ function getName(); function setName(); } interface demo{ function demo1(); } //接口的多重继承 interface CommonUser extends User,demo{ function text(); } //类继承接口是必须实现方法的 class Test implements Comm…

php面向对象编程（十）魔术方法和自动引入类机制
type: item
date: 2018-01-18T04:55:00+00:00
description: 魔术方法（魔术函数）类内部使用的方法__construct() :实例化对象时被调用；__destuct()：当删除一个对象或者对象销毁前是被执行；__get()：调用对象不存在的属性或没有声明的属性值被调用；__set()：给一个未定义的属性或没有声明的属性赋值时调用此方法；__call()：调用对象不存在方法时被调用；这里的没有声明包括当使用对象调用时，访问控制修饰符为proteced或private的属性（即没有权限访问的属性）。<?php class Human { //定义属性 public $name = "Jack"; //姓名属性 public $sex = "female"; //性别属性 public $age = 23; //年龄属性 var $addr; //通讯属性 PHP4里面声明属性 public $data = array(); //定义data属性 用来存放数据 //定义方法 public function reading() { } public function talking() { echo "Hellow world! "; } //PHPdocuments function html() {//how to make love } /** * 魔术方法 当满足特定场景时 自动调用的方法 * @param string $name 要设置的未定义属性名称 * @param mixed $value 设置的值 */ public function __set($name, $value) { // echo "你正在尝试给一个未定义的属性{$name}赋值！{$value}"; //将未定义的属性和值 以键值对 存入data属性中 在类的内部使用$this指代当前调用对象 访问属性和方法 $this->data[$name] = $value; } //读取一个未定义的属性时 自动调用的魔术方法 public function __get($name) { // echo "你正在读取未定义的属性{$name}"; echo $this->data[$name]; // return $this->data[$name]; } //访问未定义的方法时 自动调用的魔术方法 public function __call($name, $arguments) { // echo $name; // var_dump($arguments); echo "你调用了一个未定义的方法：{$name},并且携带参数："; var_dump($arguments); } } //实例化一个对象 $Jack = new Human(); //通过对象去获取属性和方法 通过"->"运算符 . echo $Jack->name."的年龄是：".$Jack->age." "; $Jack->talking(); //给一个未定义的属性赋值时 会调用魔术方法 __set(); $Jack->from = "USA"; var_dump($Jack->data); echo $Jack->from." "; //访问未定义的方法 $Jack->abc("1", "a");__callStatic()__callStatic()，用静态方式中调用一个不可访问方法时调用class Person { function say() { echo "Hello, world! "; } /** * 声明此方法用来处理调用对象中不存在的方法 */ public static function __callStatic($funName, $arguments) { echo "你所调用的静态方法：" . $funName . "(参数：" ; // 输出调用不存在的方法名 print_r($arguments); // 输出调用不存在的方法时的参数列表 echo ")不存在！ \n"; // 结束换行 } } $Person = new Person(); $Person::run("teacher"); // 调用对象中不存在的方法，则自动调用了对象中的__call()方法 $Person::eat("小明", "苹果"); $Person->say();_toString()_toString():打印一个对象时被调用，比如echo $obj ，print($obj) 。__toString()，类被当成字符串时的回应方法此方法必须返回一个字符串，否则报错或500。不能在 __toString() 方法中抛出异常。这么做会导致致命错误。<?php class Person { public $sex; public $n…

php面向对象编程（九）延迟绑定static
type: item
date: 2018-01-18T02:37:00+00:00
description: 延迟绑定static::在PHP5.3中加入了一个新特性(后期静态绑定),该特性最明显的标志就是新关键字static,用法类似于self。“后期静态绑定”的意思是说,static::不在被解析为定义当前方法所在的类,而是在实际运行时计算的。因此也称之为执行期绑定。比如当一个子类继承了父类的静态属性和方法的时候,它的值并不能改变,有是时不希望看到这种情况。<?php class Person{ static $name="张三"; const AGE=22; public static function intro(){ echo "我的名字是 ",self::$name," "; echo "我的年龄是".self::AGE," "; } public static function intro1(){ echo "我的名字是 ",static::$name," "; echo "我的年龄是".static::AGE," "; } } class stu extends Person{ static $name ="王五"; //如果我想让继承的intro方法 输出的是 "王五" 必须重写覆盖。 //那么有没有一种方法可以 在子类里面运算子类的属性呢？ //就用 static::$age延迟绑定 也就是执行期绑定 实际运算的时候计算 } Person::intro(); echo " "; Stu::intro(); echo " "; Stu::intro1();

php面向对象编程（八）常量关键字const、和traits
type: item
date: 2018-01-18T01:27:00+00:00
description: const数据语法结构 define属于函数const的使用语法:const 常量标识符 = 常量值;const关键字一般在类的声明里定义常量时使用；PHP5.3以后，可以使用const关键字在类定义的外部定义常亮const定义的常量默认为大小写敏感，通常常量标识符总是大写的。开发中尽量使用大写<?php const TEST ='test'; //等同于 define('TEST','test'); class test{ const NAME = '李四'; const name ='张三'; public function d(){ echo self::NAME," "; //name属性 echo self::name," "; //区分大小写 echo TEST," "; } } $t= new test(); $t->d(); echo test::NAME; //外部访问类常量const与definde的区别const一般用于类成员变量的定义，一经定义，不可修改。define不可用于类成员变量的定义，一般用于定义全局常量。const不能在条件语句中定义常量。const采用一个普通的常量名称，define可以采用表达式作为名称。const只能接受静态的标量，而define可以采用任何表达式。const定义的常量时大小写敏感,而define可以通过第三个参数(为true表示大小写不敏感)来指定大小写是否敏感<?php const TEST1 ='test1'; //等同于 define('TEST','test'); define('TEST','test'); class test{ // define('T1',1); //类的内部不能使用define定义常量 public function tt() { echo TEST1," "; echo TEST," "; } } $t = new test(); $t->tt(); $i=10; if($i<15){ define('AGE',12); // const CAGE =12; //const声明的常量不能出现在逻辑语句中 } echo AGE," "; //echo CAGE," "; $n = "tt".rand(1111,9999); define($n,19); //define可以用表达式$n echo constant($n); //const $n =100; //const 是不能使用表达式最为常量名称 echo " "; const TT = 2+"2"; echo TT," "; //在PHP 老版本是不支持 const值是表达式的 PHP7是可以支持的 define('DD',100+1,true); echo DD," \n",dd; //define第三个值为true的时候对大小写不敏感traitsPHP是支持单继承的。在开发这种，经常会碰见一个问题，就是这个类的方法或者属性在其他类里经常用到。但如果每个类都声明了这个属性或方法、会造成不需要的代码沉余、类也变得不是单一职责了。自PHP5.4.0起PHP实现了代码复用的一个方法，称为traits。代码案例<?php trait tDebug { //定义一个打印这个类的方法 public function dumpObject() { $class = get_class($this); $attributes = get_object_vars($this); $methods = get_class_methods($this); echo " $class 对象的信息 "; echo ' 属性 '; foreach ($attributes as $k => $v) { echo " $k: $v "; } echo ' '; echo ' 方法 '; foreach ($methods as $v) { echo " $v "; } echo ' '; } //如果引用trait的类，的方法和trait类方法相同、trait的会被覆盖 function setSize($w = 0, $h = 0) { echo "宽$w","高$h"; } function trait_setSize($w = 0, $h = 0) { echo "宽$w","高$h"; } } //定义一个矩形类 class Rectangle { use tDebug; public $width = 0; public $height = 0; function __construct($w = 0, $h = 0) { $this->width = $w; $this->height = $h…