zoukankan      html  css  js  c++  java
  • PHP面向对象的学习(封装,继承,多态)

    这个文章就是记录  巩固一下PHP的面向对象的部分 ,无非就是封装,继承,多态等等这几部分

    这里参考了一位大佬总结的文章:https://www.cnblogs.com/adaia/p/6986576.html  十分感谢

    首先面向对象的思想需要明白,类和方法(也就是函数)的定义也需要弄清楚,什么是对象?什么是类?

    1、什么是类?
     具有相同属性(特征)和方法(行为)的一系列个体的集合,类是一个抽象的概念
    2、什么是对象?
    从类中拿到的具有具体属性值得个体,称为对象,对象是一个具体的个体
    
    所以,面向对象即我们专注对象来处理问题,通过从一个个具有属性和功能的类中拿到对象来处理问题。

    0、继承

    在PHP中我们主要通过Extends关键字来实现继承   ->class Student extends Person { }

    下面是几个比较重要的注意事项:

    ①子类只能继承父类的非私有属性
    ②子类继承父类后,相当于将父类的属性和方法copy到子类,可以直接使用$this调用该属性;
    ③PHP只能单继承,不支持一个类继承多个类。但是一个类可以进行多层继承(即A继承于B,而C又继承于A,C通过A间接继承了B)

    一、封装

    类实现封装是为了不让外面的类随意的修改一个类的成员变量,所以在定义一个类的成员的时候,我们使用private关键字设置这个成员的访问权限

    只能被这个类的其他成员方法调用,而不能被其他类中的方法调用,即通过本类中提供的方法来访问本类中的私有属性。

    ①所以在该类中我们会提供一个访问私有属性的方法

    ②然后我们一般会定义两个方法来实现对一个变量的操作,即:get()与set()方法。

     

    class Person{                   
            private $name;
            private $age;
            
            public function __construct($name,$age){                    //__construct称之为构造函数 定义:在对象实例化的时候会自动执行一段代码       说白了就是自动给对象附上一些值
                $this->name = $name;
                $this->age = $age;
            }
            function setAge($age){
                if($age>=0&&$age<=120){
                    $this->age = $age;
                }else{
                    error_log("年龄设置有误!");
                }
            }
            
            function getAge(){
                return $this->age;
            }
            public function say(){
                echo "我叫{$this->name},我今年{$this->age}岁了";        //private声明的变量在这个类的其他方法里调用的格式就是  $this->xxx 
            }
            
            function __get($name){
                switch ($name) {
                    case 'name':
                        return $this ->$name."这是读取时加的文字";                    
                    case 'age':
                        return "0".$this ->$name;
                    default:
                        return $this ->$name;                    
                }
                
            }
            function __set($key,$value){
     //__set()与__get()是两个魔术方法,用于设置和输出对象里的私有成员属性的,存在于类中
    //当外面直接设置私有成员属性$name的时候被_set()自动调用 ,当外面直接使用私有成员属性$name的时候_get()被自动调用
    if($key=="name"){ $this->$key = $value."这是设置时加的文字<br>"; }else{ $this->$key = $value; } } function __isset($name){
    //php _isset()方法详细解释 : https://www.php.cn/php-weizijiaocheng-426362.html
    //_isset() 方法就是当在类外部使用isset()判定类的私有成员是否存在的时候就会调用_isset()方法
    return isset($this->$name); } function __unset($name){ if($name=="age"){ return; } unset($this->$name); } } $zhangsan = new Person("zhangsan",14); $zhangsan->setAge(12); echo $zhangsan->getAge()."<br>"; var_dump(isset($zhangsan->name)); unset($zhangsan->age); echo $zhangsan->age;

     

    三、多态

    什么是多态?

    一个类,被多个子类继承,如果这个类的某个方法,在多个子类中,表现出不同的功能,我们称这种行为为多态。(同一个类的不同子类表现出不同的形态)

    那么我们如何来实现多态呢?

    子类继承父类 ->子类重写父类方法 ->父类引用指向子类对象

    abstract class Person{           //注:父类使用abstract关键字修饰
      abstract function say();
    } 
    
    class Chinese extends Person{      //注:子类重写父类方法
      function say(){
        echo "我是中国人<br>";
      }
    } 
    class English extends Person{      //注:子类重写父类方法
      function say(){
        echo "我是英国人";
      }
    }
    
    $zhangsan = new Chinese();
    $zhangsan->say();
    $z = new English();
    $z->say();
    Person $p = new Chinese(); //注:父类引用指向子类对象
    //作用:抽象类不实现具体方法,具体方法由子类完成。
    //定义抽象类 abstract
    abstract class A{
      //abstract 定义抽象类的方法,这里没有花括号。子类必须实现这个抽象方法。
      abstract public function say();
      //抽象类可以有参数
      abstract public function eat($argument);
      //在抽象类中可以定义普通的方法。
      public function run(){
        echo '这是run方法';
      }
    }
    class B extends A{
      //子类必须实现父类的抽象方法,否则是致命的错误。
      public function say(){
        echo '这是say方法,实现了抽象方法';
      }
      public function eat($argument){
        echo '抽象类可以有参数 ,输出参数:'.$argument;
      }
    }
    $b =new B;
    $b->say();
    echo '<br>';
    $b->eat('apple');
    echo '<br>';
    $b->run();

    定义为抽象的类不能被实例化。任何一个类,如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。

    继承一个抽象类的时候,子类必须定义父类中的所有抽象方法;另外,这些方法的访问控制必须和父类中一样(或者更为宽松)。例如某个抽象方法被声明为受保护的,那么子类中实现的方法就应该声明为受保护的或者公有的,而不能定义为私有的。此外方法的调用方式必须匹配,即类型和所需参数数量必须一致。例如,子类定义了一个可选参数,而父类抽象方法的声明里没有,则两者的声明并无冲突。 这也适用于 PHP 5.4 起的构造函数。在 PHP 5.4 之前的构造函数声明可以不一样的。

    参考文章:https://www.php.net/manual/zh/language.oop5.abstract.php

    * 四、单例设计模式


    单例模式也叫单态模式
    可以保证一个类只能有一个对象实例
    实现要点:
    ①构造函数私有化,不允许使用new关键字创建对象。
    ②对外提供获取对象的方法,在方法中判断对象是否为空,如果为空则创建对象并返回,如果不为空则直接返回
    ③实例对象的属性以及获取对象的方法必须都是静态的
    ④之后,创建对象只能使用我们提供的静态方法。

    示例代码如下:

    class Singleton{
      static public $Single = null;
      private function __construct(){}
      static function getSingle()  {
        if(!self::$Single){
          self::$Single = new Singleton();//self代指类名 new Singleton()和newself()是完全一样的
    //静态方法调用静态属性,使用self关键词 //echo $this->height 这么表示是错的。静态方法不能调用非静态属性 因为 $this代表实例化对象,而这里是类,不知道 $this 代表哪个对象
        }     return self::$Single;   }   function __destruct()  {     echo "我被销毁了<br>";   } } $s1 = Singleton::getSingle(); $s1 = Singleton::getSingle(); $s1 = Singleton::getSingle();

    五、PHP重载

    这里需要注意的是,PHP这个语言是没有方法重载的,只有属性重载

    属性重载:

    含义:对一个对象的不存在的属性进行使用的时候,这个类种预先设定好的应对方法(处理机制)

    属性,本质就是一个变量,其有4个操作:

     

    取值:当对一个对象的不存在的属性进行“取值”的时候,就会自动调用方法:__get();

    赋值:当对一个对象的不存在的属性进行“取值”的时候,就会自动调用方法:__set();

    判断(isset):当对一个对象的不存在的属性进行“判断”的时候,就会自动调用方法:__isset();

    判断(isset):当对一个对象的不存在的属性进行“判断”的时候,就会自动调用方法:__unset()。

    __set($属性名,值):

     

    含义:当对一个对象的不存在属性进行“赋值”的时候就会自动调用这个内部的魔术方法,它有两个形参,分别代表对不存在的属性进行赋值的时候的“属性名”和“属性值”。

     这个方法结合__get()方法,往往可以使我们定义的类,就有一种“可简便扩展属性”的特性,即类(或对象)的属性,可以更为方便自由,如下所示:

    class A{

        protected $prop_list = array();

        function __set($p,$v){

            $this->prop_list[$p] = $v;

        }

        function __get($p){

            return $this->prop_list[$p];

        }

    }

    __isset()

     含义:当对一个对象的不存在属性进行“判断”的时候就会自动调用这个内部的魔术方法。

    __unset()

     含义:当对一个对象的不存在属性进行“销毁”的时候就会自动调用这个内部的魔术方法。

    六、对象接口

    使用接口(interface),可以指定某个类必须实现哪些方法,但不需要定义这些方法的具体内容。

    接口是通过 interface 关键字来定义的,就像定义一个标准的类一样,但其中定义所有的方法都是空的。

     

    定义形式

     

    interface 接口名 {

        常量1;

        常量2;

        ...

        抽象方法1;

        抽象方法2;

        ...

    }

     

    说明:

    接口中只有常量(接口常量)和抽象方法两种成员;

    接口常量的使用形式为:接口名称::常量名称;

    接口中的抽象方法,不要使用abstract修饰,也需要使用访问控制修饰符,因为其天然就是Public;

    php中接口和类一样也可以继承(接口继承接口)。

    还谈php和java面向对象

     

    相同点:

    抽象类和抽象方法,及它们之间的细节都一样;

    php的接口和java的接口都一样。

    不同点:

    重载不一样,php重载和其他面向对象语言的重载不同,而java和其他面向对对象语言的重载一样。

     

     

     

  • 相关阅读:
    搜狗图片抓取,主要以图集类进行抓取
    使用mongo进行去重操作
    爬虫实战01_淘宝模拟登录
    Linux常用命令02(远程管理)
    Linux常用命令01(文件和目录)
    Linux终端命令格式
    常用Linux命令的基本使用
    闭包与私有变量
    三栏布局的几种方法
    redux和react-redux小记
  • 原文地址:https://www.cnblogs.com/zhangqianxi/p/13865001.html
Copyright © 2011-2022 走看看