php代码之面向对象基础一_PHP教程
php代码之面向对象基础一
这篇文章不适合于初学者看,对php有一定了解的可以看一下,补充或者温故一下php面向对象里的一些特性。
一.何为面向对象?
介个问题,虽然略知一二,却感觉依然拿不出手,只能说将万事万物皆看为对象,只有在开发中才能体会出何为面向对象,只说也是徒然,但因为php大多用在web开发,所以,即使不使用面向对象也能运行的不错,之前在做c++开发时,设计给你个功能界面,看到这个界面,第一件事就是像美工切图一样的切成一个个的对象,然后,确定各个对象之间的关系,最后进行开发,哪儿都充斥着此思想。
什么是类?什么是对象?
类是一组集合的抽象,什么集合呢?是一组具有相似特性和操作的对象的集合。
对象是某一个类的具体实例。
毕业时候可能我会背给面试官听,可现在,虽然感觉理解的还是想书本上的语句一样的俗,但起码不用再靠脑细胞说出这两个定义。
二.php中的类结构
php中类也是那些访问控制符,也是有属性和方法。
class Person { private $name = "PersonName"; public static $gender = "PersonGender"; public function test(){ echo $this->name, '<br />'; } };
构造函数的名称为__construct,在构造函数这里我想强调的有以下几点:
1. php不会像其他语言(c++或者java)那样,当实例化子类的时候会自动调用你的父类构造函数,php里需要手动调用父类的构造函数,这儿牵扯到继承,可以先看一下继承方面的东西。
class Person{ public funciton __construct(){ echo 'Person construct<br />'; } }; class Teacher extends Person{ public function __construct(){ //parent::__construct(); echo 'Teacher construct<br />'; } }; $t1 = new Teacher; //生成Teacher对象
运行结果:
Teacher construct
如果想要在生成子类时初始化父类的一些数据,需要手动调用父类的构造函数,打开注释行即可。
2. 一个类中不能写两个参数不同的构造函数。
这儿牵扯到php中的一些规定,其他语言中,以下写法是正确的:
class Person{ public funciton __construct(){ echo 'Person construct<br />'; } public function __construct($param){ echo 'Person with param construct<br />'; } };
而在php是不允许的,究其根源为php是一种弱语言类型,对于类型的限制不是很敏感,进而提供了__call和func_get_args函数机制,因而可以用如下的方式实现:
class Person{ public function __construct(){ $param = func_get_arg(); //获取参数数据 $param_num = func_num_args(); //获取参数个数 if($param_num == 0){ }else if($param_num == 1){ if(is_array($param[0])){ //... } }else{ //... } } };
三.析构函数
析构函数是用于在此实例对象结束时,自动调用的函数,可以写入一下释放内存的语句来为实例的死亡画上完美的句号,这儿与构造相同,有继承关系时必须手动调用父类的析构,一个类中只有一个析构。
四.控制访问符
public:公共访问符,在类内,子类内,类外都可以访问此属性或方法。
protected:受保护的访问符,只能在类内和其子类内访问此属性或方法,在类外不能访问。
private:私有访问符,只能在本类内访问,属于本类私有东东,不能继承,不能重载,任何人访问不了。
五.魔术方法__get和__set
这两个方法的功能:对受保护和私有属性访问的一个访问器,可以对从类外接收到的数据进行安全性和合理性的校验。
__set方法接收两个参数,第一个是属性名称,第二个是要赋的新值。
__get方法接收一个参数,属性名称。
1. public属性能提供在类外修改属性的服务,因此,对于public属性,不会走__get和__set流程。
class D{ public $name = 'D name'; protected $gender = 'male'; private $age = 18; public function __set($name, $value){ echo '__set<br />'; //if(in_array($name, ['name', 'gender', 'age'])) $this->$name = $value; } public function __get($name){ echo '__get<br />'; //if(!in_array($name, ['name', 'gender', 'age'])) return NULL; return $this->$name; } };
运行结果:
new D name //name为public属性,不会走get和set __set __get new D gender __set __get new D age
2. 我们也可以加入数据校验的功能,打开注释就可以进行校验。
3.两个方法必须是public访问,否则会提示错误,我们可以从这两个函数的功能来出发思考,就不难想象为什么需要public访问控制。
六.继承
终于到了可以让你的菊花开苞的特性,没有继承,所有类都是渣渣,因为有了继承,所以...问题就特么的一大波一大波的来啦...让我们来深入浅出一下此继承特性。
什么继承就不说了吧,文章的开头就有一个继承的小示例。
有了继承会出现什么问题呢?想一下,如果B继承了A...真的是难以想象...
1. 构造函数,这个放心,跟继承没有太多关系,相当于两个类里的构造函数,但是怎么也有个父子关系啊,不能把事做的太绝,所以,上面讲过,如果有需要,可以手动调用父类的构造函数,可以看下上面的示例。
2.单方向继承,继承是单方向的,子类可以从父类继承,但父类却不能从子类继承特性,示例:
class A{ public $attr1; public function oper1(){ } }; class B extends A{ public $attr2; public function oper2(){ } }; //子类可以继承父类 $b = new B; $b->oper1(); $b->attr1 = 'attr1 value'; $b->oper2(); $b->attr2 = 'attr2 value'; //父类不能继承子类 $a = new A; $a->oper2();//出错 $a->attr1();//出错
3. 重载,一提到php的重载就特别别扭,因为他的重载放到其他语言里叫做重写overwrite,我还是习惯将这个特性说为重写,大家随便。
<1>public重载:
class E{ public $attr1 = 'E attr1 value'; public function oper1(){ echo 'E oper1<br />'; echo 'attr1 value = ', $this->attr1, '<br />'; } }; class F extends E{ public $attr1 = 'F attr1 value'; public function oper1(){ //parent::oper1(); echo 'F oper1<br />'; echo 'attr1 value = ', $this->attr1, '<br />'; } }; $f = new F; $f->oper1();
运行结果:
F oper1
attr1 value = F attr1 value
F继承了E并且重写了E的attr1和oper1,因此,在调用oper1时,$this->attr1显示F attr1 value,如果打开注释parent::oper1调用父类的Oper1方法,运行结果如下:
E oper1
attr1 value = F attr1 value //attr1属性已经被子类重写的attr1属性覆盖
F oper1
attr1 value = F attr1 value
可以看出子类重写父类的属性和方法后,会覆盖父类相应的属性和方法。
<2>private重载
class E{ private $attr1 = 'E attr1 value'; public function oper1(){ echo 'E oper1<br />'; echo 'attr1 value = ', $this->attr1, '<br />'; } }; class F extends E{ public $attr1 = 'F attr1 value'; public function oper1(){ parent::oper1(); echo 'F oper1<br />'; echo 'attr1 value = ', $this->attr1, '<br />'; } }; $f = new F; $f->oper1();
E oper1
attr1 value = E attr1 value //父类私有的属性
F oper1
attr1 value = F attr1 value
之前我们说过,private属性和方法子类是继承不了的,这种情况,遵循一个原则:
private属性在那个类里调用的,就显示哪个类里的属性值。
示例中的parent::oper1方法调用的是E类的oper1方法,在E的oper1方法内又调用了$this->attr1,attr1是private并没有被子类继承,因此,调用的就是类E里的attr1属性值。
<3>protected重载与public重载一致
<4>类属性的继承
class G{ public static $attr1 = 'G attr1 value'; public function oper1(){ echo 'G oper1<br />'; echo 'attr1 value = ', self::$attr1, '<br />'; } }; class H extends G{ public static $attr1 = 'H attr1 value'; public function oper1(){ parent::oper1(); echo 'H oper1<br />'; echo 'attr1 value = ', self::$attr1, '<br />'; } }; $h = new H; $h->oper1();
运行结果:
G oper1
attr1 value = G attr1 value
H oper1
attr1 value = H attr1 value
其实不管G类的attr1属性是public还是private,结果都一样。
个人是这么理解的,类属性可以继承,但谈不上重载,那关于子类调用父类的属性也有一规则:
self或者parent只代表本类,因此,根据这一原则可以断定,属性的值一定是本类属性的值,与子类无关。(特殊情况时php的静态延迟加载机制)。
七.静态延迟加载
既然已经提到了静态延迟加载,就趁热打铁讲一下,H和G的例子大家已经看了,那我就是想要在子类中调用父类的东东怎么办?静态延迟加载就是解决这个问题,请看两个示例:
示例1:
还是H和G类的例子
class G{ public static $attr1 = 'G attr1 value'; public function oper1(){ echo 'G oper1<br />'; echo 'attr1 value = ', static::$attr1, '<br />'; } }; class H extends G{ public static $attr1 = 'H attr1 value'; public function oper1(){ parent::oper1(); echo 'H oper1<br />'; echo 'attr1 value = ', self::$attr1, '<br />'; } }; $h = new H; $h->oper1();
G oper1
attr1 value = H attr1 value
H oper1
attr1 value = H attr1 value
上面代码只是将G类里的self::$attr1改写成了static::$attr1,运行结果就不一样了
示例2:
class I { public static function who(){ echo __CLASS__, '<br />'; } public static function test(){ static::who(); } }; class J extends I{ public static function who(){ echo __CLASS__,'<br />'; } };
运行结果:
J
通过这两个例子,可以好好的领悟一下static的静态延迟绑定。
写的有点多,主要是因为一牵扯继承就停不下来....面向对象还有一些只是点,后面有时间再补上吧...谢谢,如若有错误的地方,敬请大家指出,随时更正,谢谢!!

热AI工具

Undresser.AI Undress
人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover
用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

Video Face Swap
使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热门文章

热工具

记事本++7.3.1
好用且免费的代码编辑器

SublimeText3汉化版
中文版,非常好用

禅工作室 13.0.1
功能强大的PHP集成开发环境

Dreamweaver CS6
视觉化网页开发工具

SublimeText3 Mac版
神级代码编辑软件(SublimeText3)

热门话题

蓝屏代码0x0000001怎么办蓝屏错误是电脑系统或硬件出现问题时的一种警告机制,代码0x0000001通常表示出现了硬件或驱动程序故障。当用户在使用电脑时突然遇到蓝屏错误,可能会感到惊慌和无措。幸运的是,大多数蓝屏错误都可以通过一些简单的步骤进行排除和处理。本文将为读者介绍一些解决蓝屏错误代码0x0000001的方法。首先,当遇到蓝屏错误时,我们可以尝试重

终止代码0xc000007b在使用电脑时,有时会遇到各种各样的问题和错误代码。其中,终止代码最为令人困扰,尤其是终止代码0xc000007b。这个代码表示某个应用程序无法正常启动,给用户带来了不便。首先,我们来了解一下终止代码0xc000007b的含义。这个代码是Windows操作系统的错误代码,通常发生在32位应用程序尝试在64位操作系统上运行时。它表示应

0x000000d1蓝屏代码是什么意思近年来,随着计算机的普及和网络的快速发展,操作系统的稳定性和安全性问题也日益凸显。一个常见的问题是蓝屏错误,代码0x000000d1是其中之一。蓝屏错误,或称为“蓝屏死机”,是当计算机遇到严重系统故障时发生的一种情况。当系统无法从错误中恢复时,Windows操作系统会显示一个蓝色的屏幕,并在屏幕上显示错误代码。这些错误代

如果您需要远程编程任何设备,这篇文章会给您带来帮助。我们将分享编程任何设备的顶级GE通用远程代码。通用电气的遥控器是什么?GEUniversalRemote是一款遥控器,可用于控制多个设备,如智能电视、LG、Vizio、索尼、蓝光、DVD、DVR、Roku、AppleTV、流媒体播放器等。GEUniversal遥控器有各种型号,具有不同的功能和功能。GEUniversalRemote最多可以控制四台设备。顶级通用遥控器代码,可在任何设备上编程GE遥控器配备一组代码,使其能够与不同设备相配合。您可

快速上手Python绘图:画出冰墩墩的代码示例Python是一种简单易学且功能强大的编程语言,通过使用Python的绘图库,我们可以轻松地实现各种绘图需求。在本篇文章中,我们将使用Python的绘图库matplotlib来画出冰墩墩的简单图形。冰墩墩是一只拥有可爱形象的熊猫,非常受小朋友们的喜爱。首先,我们需要安装matplotlib库。你可以通过在终端运行

作为一名程序员,对于能够简化编码体验的工具,我感到非常兴奋。借助人工智能工具的帮助,我们可以生成演示代码,并根据需求进行必要的修改。在VisualStudioCode中新引入的Copilot工具让我们能够创建具有自然语言聊天交互的AI生成代码。通过解释功能,我们可以更好地理解现有代码的含义。如何使用Copilot生成代码?要开始,我们首先需要获得最新的PowerPlatformTools扩展。要实现这一点,你需要进入扩展页面,搜索“PowerPlatformTool”,然后点击Install按钮

将MySQL查询结果数组转换为对象的方法如下:创建一个空对象数组。循环结果数组并为每一行创建一个新的对象。使用foreach循环将每一行的键值对赋给新对象的相应属性。将新对象添加到对象数组中。关闭数据库连接。

在Linux操作系统中处理文件需要使用各种命令和技术,使开发人员能够高效地创建和执行文件、代码、程序、脚本和其他东西。在Linux环境中,扩展名为”.a”的文件作为静态库具有重要的重要性。这些库在软件开发中发挥着重要作用,允许开发人员有效地管理和共享多个程序的公共功能。对于Linux环境中的有效软件开发,了解如何创建和运行“.a”文件至关重要。本文将介绍如何全面安装和配置Linux“.a”文件,让我们一起探索Linux“.a”文件的定义、用途、结构,以及创建和执行它的方法。什么是L
