• 技术文章 >后端开发 >php教程

    php代码之面向对象基础一_PHP教程

    2016-07-13 10:02:40原创318

    php代码之面向对象基础一


    这篇文章不适合于初学者看,对php有一定了解的可以看一下,补充或者温故一下php面向对象里的一些特性。


    一.何为面向对象?

    介个问题,虽然略知一二,却感觉依然拿不出手,只能说将万事万物皆看为对象,只有在开发中才能体会出何为面向对象,只说也是徒然,但因为php大多用在web开发,所以,即使不使用面向对象也能运行的不错,之前在做c++开发时,设计给你个功能界面,看到这个界面,第一件事就是像美工切图一样的切成一个个的对象,然后,确定各个对象之间的关系,最后进行开发,哪儿都充斥着此思想。

    什么是类?什么是对象?

    类是一组集合的抽象,什么集合呢?是一组具有相似特性和操作的对象的集合。

    对象是某一个类的具体实例。

    毕业时候可能我会背给面试官听,可现在,虽然感觉理解的还是想书本上的语句一样的俗,但起码不用再靠脑细胞说出这两个定义。


    二.php中的类结构

    php中类也是那些访问控制符,也是有属性和方法。

    class Person {
        private $name = "PersonName";
        public static $gender = "PersonGender";
        
        public function test(){
            echo $this->name, '
    '; } };


    三.构造函数

    构造函数的名称为__construct,在构造函数这里我想强调的有以下几点:

    1. php不会像其他语言(c++或者java)那样,当实例化子类的时候会自动调用你的父类构造函数,php里需要手动调用父类的构造函数,这儿牵扯到继承,可以先看一下继承方面的东西。

    class Person{
    	public funciton __construct(){
    		echo 'Person construct
    '; } }; class Teacher extends Person{ public function __construct(){ //parent::__construct(); echo 'Teacher construct
    '; } }; $t1 = new Teacher; //生成Teacher对象

    运行结果:

    Teacher construct

    如果想要在生成子类时初始化父类的一些数据,需要手动调用父类的构造函数,打开注释行即可。


    2. 一个类中不能写两个参数不同的构造函数。

    这儿牵扯到php中的一些规定,其他语言中,以下写法是正确的:

    class Person{
    	public funciton __construct(){
    		echo 'Person construct
    '; } public function __construct($param){ echo 'Person with param construct
    '; } };


    而在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
    '; //if(in_array($name, ['name', 'gender', 'age'])) $this->$name = $value; } public function __get($name){ echo '__get
    '; //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
    '; echo 'attr1 value = ', $this->attr1, '
    '; } }; class F extends E{ public $attr1 = 'F attr1 value'; public function oper1(){ //parent::oper1(); echo 'F oper1
    '; echo 'attr1 value = ', $this->attr1, '
    '; } }; $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
    '; echo 'attr1 value = ', $this->attr1, '
    '; } }; class F extends E{ public $attr1 = 'F attr1 value'; public function oper1(){ parent::oper1(); echo 'F oper1
    '; echo 'attr1 value = ', $this->attr1, '
    '; } }; $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属性值。


    <3>protected重载与public重载一致


    <4>类属性的继承

    class G{
        public static $attr1 = 'G attr1 value';
        public function oper1(){
            echo 'G oper1
    '; echo 'attr1 value = ', self::$attr1, '
    '; } }; class H extends G{ public static $attr1 = 'H attr1 value'; public function oper1(){ parent::oper1(); echo 'H oper1
    '; echo 'attr1 value = ', self::$attr1, '
    '; } }; $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
    '; echo 'attr1 value = ', static::$attr1, '
    '; } }; class H extends G{ public static $attr1 = 'H attr1 value'; public function oper1(){ parent::oper1(); echo 'H oper1
    '; echo 'attr1 value = ', self::$attr1, '
    '; } }; $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__, '
    '; } public static function test(){ static::who(); } }; class J extends I{ public static function who(){ echo __CLASS__,'
    '; } };

    运行结果:

    J


    通过这两个例子,可以好好的领悟一下static的静态延迟绑定。


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



    www.bkjia.comtruehttp://www.bkjia.com/PHPjc/969602.htmlTechArticlephp代码之面向对象基础一 这篇文章不适合于初学者看,对php有一定了解的可以看一下,补充或者温故一下php面向对象里的一些特性。 一.何...

    声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。
    专题推荐:对象 代码 基础
    上一篇:win7下安装与配置php_PHP教程 下一篇:《pigcms v6.2最新完美至尊版无任何限制,小猪微信源码多用户微信营销服务平台系统》,小猪pigcmsv8.1下载_PHP教程
    20期PHP线上班

    相关文章推荐

    • 【活动】充值PHP中文网VIP即送云服务器• PHP写入XML文件事字表数据只读一条数据,什么原因 • ThinkPHP兑现在线生成准考证 • 【PHP】界别include(),require(),include_once(),require_once() • js 弹窗出现乱码了解决方案 • 关于appserv的有关问题
    1/1

    PHP中文网