首页 后端开发 php教程 php代码之面向对象基础一

php代码之面向对象基础一

Jun 23, 2016 pm 01:38 PM

这篇文章不适合于初学者看,对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__getnew D gender__set__getnew 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,我还是习惯将这个特性说为重写,大家随便。

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

可以看出子类重写父类的属性和方法后,会覆盖父类相应的属性和方法。


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();
登录后复制
以上代码只变动了一处地方,就是把父类$attr1的访问属性变成private,那重载机制如何执行呢?先看运行结果:

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属性值。


protected重载与public重载一致


类属性的继承

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的静态延迟绑定。


写的有点多,主要是因为一牵扯继承就停不下来....面向对象还有一些只是点,后面有时间再补上吧...谢谢,如若有错误的地方,敬请大家指出,随时更正,谢谢!!



本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳图形设置
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
威尔R.E.P.O.有交叉游戏吗?
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

在PHP API中说明JSON Web令牌(JWT)及其用例。 在PHP API中说明JSON Web令牌(JWT)及其用例。 Apr 05, 2025 am 12:04 AM

JWT是一种基于JSON的开放标准,用于在各方之间安全地传输信息,主要用于身份验证和信息交换。1.JWT由Header、Payload和Signature三部分组成。2.JWT的工作原理包括生成JWT、验证JWT和解析Payload三个步骤。3.在PHP中使用JWT进行身份验证时,可以生成和验证JWT,并在高级用法中包含用户角色和权限信息。4.常见错误包括签名验证失败、令牌过期和Payload过大,调试技巧包括使用调试工具和日志记录。5.性能优化和最佳实践包括使用合适的签名算法、合理设置有效期、

描述扎实的原则及其如何应用于PHP的开发。 描述扎实的原则及其如何应用于PHP的开发。 Apr 03, 2025 am 12:04 AM

SOLID原则在PHP开发中的应用包括:1.单一职责原则(SRP):每个类只负责一个功能。2.开闭原则(OCP):通过扩展而非修改实现变化。3.里氏替换原则(LSP):子类可替换基类而不影响程序正确性。4.接口隔离原则(ISP):使用细粒度接口避免依赖不使用的方法。5.依赖倒置原则(DIP):高低层次模块都依赖于抽象,通过依赖注入实现。

解释PHP中晚期静态结合的概念。 解释PHP中晚期静态结合的概念。 Mar 21, 2025 pm 01:33 PM

文章讨论了PHP 5.3中引入的PHP中的晚期静态结合(LSB),从而允许静态方法的运行时分辨率调用以获得更灵活的继承。 LSB的实用应用和潜在的触摸

如何用PHP的cURL库发送包含JSON数据的POST请求? 如何用PHP的cURL库发送包含JSON数据的POST请求? Apr 01, 2025 pm 03:12 PM

使用PHP的cURL库发送JSON数据在PHP开发中,经常需要与外部API进行交互,其中一种常见的方式是使用cURL库发送POST�...

框架安全功能:防止漏洞。 框架安全功能:防止漏洞。 Mar 28, 2025 pm 05:11 PM

文章讨论了框架中的基本安全功能,以防止漏洞,包括输入验证,身份验证和常规更新。

如何在系统重启后自动设置unixsocket的权限? 如何在系统重启后自动设置unixsocket的权限? Mar 31, 2025 pm 11:54 PM

如何在系统重启后自动设置unixsocket的权限每次系统重启后,我们都需要执行以下命令来修改unixsocket的权限:sudo...

自定义/扩展框架:如何添加自定义功能。 自定义/扩展框架:如何添加自定义功能。 Mar 28, 2025 pm 05:12 PM

本文讨论了将自定义功能添加到框架上,专注于理解体系结构,识别扩展点以及集成和调试的最佳实践。

See all articles