zoukankan      html  css  js  c++  java
  • 对象的继承特性

    一、对象的继承

      1)什么是继承?

        父类的内容可以拿到子类当中来使用

      2)为什么要使用继承?

        ①更好地体现面向对象的可重用性

        ②避免代码的冗余

        ③可以在父类的基础上进行功能的扩展

        ④体现了面向对象的可扩展性

      3)什么时候使用继承?

        ①在功能要进行扩展的时候进行继承

        ②在功能要进行修改的时候,子类的功能会覆盖父类的功能

      4)PHP继承的特性:

        ①只支持单一继承,不支持多重继承

        ②一个子类只允许有一个父类

        ③一个父类可以有多个子类

      5)PHP继承的关键字

        ①父类、基类、超类

        ②子类、扩展类、派生类

      6)权限问题

        ①public:公有的成员在子类中可以被完全继承;子类中的成员如果与父类的公有成员的名称相同,则子类的成员功能将覆盖父类的成员功能;

        ②protected:受保护的成员在子类当中可以被完全继承;受保护的成员在子类中如果出现同名的成员,功能会被覆盖;

        ③private:父类中私有的成员在子类中不能直接拿来使用,不可被继承

        ④private < protected < public,子类中的同名的成员的权限一定要比父类的成员的权限宽松

      7)方法的重载(覆盖)

        parent::__construct();

        parent::成员方法名();

    class Person{
        public $name;
        public $sex;
        public $age;
    
        function __construct($name,$sex,$age){
            $this->name=$name;
            $this->sex=$sex;
            $this->age=$age;
        }
    
        public function say(){
            echo "my name is ".$this->name.", my sex is ".$this->sex.", my age is ".$this->age;
        }
    }
    
    class Student extends Person{
        //继承成员属性$name、$sex、$age
        public $school;
    
        //构造方法同样被继承,并被覆盖重写
        function __construct($name,$sex,$age,$school){
            //将父类的构造方法的方法体继承下来
            parent::__construct($name,$sex,$age);
    
            $this->school=$school;
        }
    
        //将父类的say方法覆盖重写
        public function say(){
            //将父类的say方法的方法体继承下来
            parent::say();
    
            echo ", my shcool is ".$this->school;
        }
    }
    
    $p=new Student("autumn","男",25,"haha");
    $p->say();

    二、常用的关键字

      1)final

        ①final修饰的成员方法不允许在子类当中被重写,为了防止已经写好的功能被修改

        ②final只能修饰方法和类,不能修饰成员属性

        ③final修饰的类不能再被其他类继承

      2)static

        ①static修饰的成员属性,在类的方法体中要使用“self::$属性名称”访问

        ②static修饰的成员属性保存在内存中的初始化静态段中,而在类中使用“$this->属性”所调用的成员属性是保存在堆当中的,所以static修饰的成员属性不能使用“$this->属性名称”来访问

        ③静态成员属性在类的外部可通过“类名::$成员属性名称”调用,不可使用对象来调用

        ④静态成员属性效率较高,因为不需要实例化对象即可调用

        ⑤同一个类的多个实例化对象共享一个静态成员属性

        ⑥静态的成员方法中不允许使用$this调用成员属性

        ⑦静态的成员方法在类的内部可以使用$this调用,也可以使用“self::方法名()”调用

        ⑧静态的成员方法在类的外部可以使用实例化对象调用,也可以使用“类名::方法名()”调用

        ⑨成员方法当中如果没有包含任何$this,该方法默认为静态成员方法

    class Person{
        public $username;
        public static $name;
    
        public function info(){
            //普通成员属性的调用
            //echo $this->username;
    
            //静态成员属性的调用
            echo self::$name;
        }   
    
        public static function say(){
            echo self::$name." say 'hello world!'";
        } 
    
        public function test(){
            //可以使用$this调用静态成员方法
            //$this->say();
    
            //也可使用“self::方法名()”调用
            self::say();
        }
    }
    
    //静态成员属性不可以使用对象来调用
    $p1=new Person;
    Person::$name="autumn";
    
    $p2=new Person;
    Person::$name="HaHa";
    
    //多个实例化对象共享一个静态成员属性
    
    $p1->info();
    $p2->info();
    
    echo "<hr>";
    
    //可以用实例化对象调用静态成员方法
    //$p1->say();
    //也可以使用“类名::方法名()”调用(推荐使用)
    Person::say();

      3)单态设计模式

        ①什么是单态(单例)(单对象)设计模式?

          让类只能实例化一个对象

        ②为什么要使用单态?

          为了节省空间、提高效率

        ③什么时候使用单态设计模式?

          数据库的连接池操作、文件资源的操作、GD资源的操作

        ④如何使用单态设计模式?

          1.构造方法私有化,外部无法自动实例化对象

          2.声明一个方法,在该方法中实例化对象

          3.将产生的对象存入至一个共享的静态成员属性中

          4.在外部想要再次实例化对象时,将该静态成员属性中的对象传给它,即仍为首次实例化的那个对象

    class Person{
        public static $obj;  //用于保存首次实例化的对象
        public $name;
    
        //构造方法私有化,外部无法自动实例化对象
        private function __construct($name){
            $this->name=$name;
        }
    
        public static function getObj($name){
            //判断该类的对象是否存在
            if(is_null(self::$obj)){
                self::$obj=new self($name);
            }
            //除首次实例化对象外,其余直接将首次实例化后存在静态成员属性中的对象传递过去
            return self::$obj;
        }  
    
        public function info(){
            echo $this->name;
        }
    }
    
    
    $p1=Person::getObj("autumn");
    var_dump($p1);
    
    echo "<hr>";
    
    $p2=Person::getObj("haha");
    var_dump($p2);

    object(Person)#1 (1) { ["name"]=> string(6) "autumn" }


    object(Person)#1 (1) { ["name"]=> string(6) "autumn" }

      4)const

        ①常量名一般情况下用大写

        ②常量值为标量数据类型

        ③常量不要加“$”

        ④常量在类的内部访问用“self::常量名”

        ⑤常量在类的外部访问用“类名::常量名”

      5)instanceof

        ①判断一个对象是否为一个类实例化的

        ②判断一个对象是否为继承父类的某个子类实例化的

    class Person{
        //声明一个常量成员属性
        const DB_HOST="localhost";
    
        public function info(){
            //类的内部调用常量成员属性
            echo self::DB_HOST;
        }   
    }
    
    class Student extends Person{
        public $school="hehe";
    
        public function say(){
            parent::info();
            echo ", my school is ".$this->school;
        }
    }
    
    //类的外部调用常量成员属性
    echo Person::DB_HOST;
    
    echo "<hr>";
    
    $p=new Person;
    $s=new Student;
    
    //instanceof用于检测当前实例对象是否属于某一个类
    var_dump($p instanceof Student);  //false
    var_dump($s instanceof Student);  //true
    var_dump($s instanceof Person);  //true

    三、常用的魔术方法

      1)克隆对象

        ①什么是克隆?

          将一个对象完整的复制一份,这个对象与原对象一模一样

        ②克隆的目的

          当对一个已经产生的对象进行一系列的修改、赋值等操作后,需要使用多个经操作后的对象时,使用克隆

        ③方法:__clone()

          参数:无

          触发时机:在使用clone对象的一瞬间自动调用

          作用:将克隆出的对象进行微调,源对象不会被影响

      2)__toString()

        参数:无

        触发时机:当在类的外部直接echo对象时,自动调用

        作用:为了更好地操作对象

        注意:本方法一定要有返回值

      3)__call()

        参数:两个(第一个是调用方法的名称,第二个是实际参数的数组)

        触发时机:当调用一个不存在的成员方法时自动调用,且将方法的名称传递给第一个参数,将方法的调用参数传递给第二个参数

        作用:避免程序报错,影响后续代码执行

    class Person{
        private $name="autumn";
        private $sex="男";
        private $age=25;
    
        public function info(){
            echo "姓名:".$this->name.",性别:".$this->sex.",年龄:".$this->age;
        }
    
        //在使用clone对象的瞬间自动调用__clone()方法
        function __clone(){
            $this->name=$this->name."_clone001";
        }
    
        //在类的外部echo对象时自动调用__toString()方法
        function __toString(){
            return "在类的外部直接echo对象会输出该段文字";
        }
    
        //当调用一个不存在的成员方法时自动调用__call()方法
        function __call($funcName,$args){
            echo "对不起,您要找的方法".$funcName."(".join(',',$args).")不存在!";
        }
    }
    
    $p1=new Person;
    
    //将对象$p1完整克隆一份
    $p2=clone $p1;
    
    var_dump($p1);
    echo "<hr>";
    var_dump($p2);
    
    echo "<hr>";
    echo $p1;
    
    echo "<hr>";
    $p1->noFunc('参数1','参数2','参数3');

      4)__sleep()

        参数:无

        触发时机:当对一个对象序列化的时候自动调用

        作用:让用户可以自定义要序列化的成员属性

        注意:该方法一定要返回一个数组类型的值,数组元素的值即为成员属性的名称

      5)__wakeup()

        参数:无

        触发时机:当对对象进行反序列化的时候自动调用

        作用:反序列化对象时使对象中的成员发生改变

      6)对象串行化(序列化)

        将对象转化成以固定形式存储的字符串

        ①为什么使用对象的串行化?

          为了能够让保存对象的介质能够识别对象的格式

        ②何时使用对象的串行化?

          要将对象存入到数据库或是文件中

          对象在网络中传输的时候可串行化

        ③方法:

          serialize($obj):串行化(序列化)

          unserialize($str):反串行化(反序列化),将对象反串行化时必须有原型类同时在

    class Person{
        private $name="autumn";
        private $sex="男";
        private $age=25;
    
        public function info(){
            echo "姓名:".$this->name.",性别:".$this->sex.",年龄:".$this->age;
        }
    
        public function __sleep(){
            //指定要序列化的成员属性
            return array('name','sex');
        }
    }
    
    $p=new Person;
    
    echo $str=serialize($p);
    
    file_put_contents("./obj.txt",$str);
    class Person{
        private $name="autumn";
        private $sex="男";
        private $age=25;
    
        public function info(){
            echo "姓名:".$this->name.",性别:".$this->sex.",年龄:".$this->age;
        }
    
        public function __sleep(){
            //指定要序列化的成员属性
            return array('name','sex');
        }
    
        public function __wakeup(){
            $this->name="admin";
            $this->sex="保密";
        }
    
        public function say(){
            echo "haha";
        }
    }
    
    $str=file_get_contents("./obj.txt");
    
    //将对象反序列化时,必须要原对象类同时在
    $obj=unserialize($str);
    
    $obj->info();

      7)__autoload()

        参数:一个(类的名称)

        触发时机:当要实例化或继承使用未经include引入的类文件中的类的时候会自动调用该函数,且会将类名作为参数传入该函数,此时在该函数内部可实现类文件的加载

        作用:用于加载类文件,无需像使用include加载类文件那样考虑加载的先后顺序

        注意:这是一个函数并非是类的成员方法,不是用于类的内部的,而是在需要引用类文件时使用的

    function __autoload($className){
        if($className=='class1'){
            include "../".$className.".class.php";
        }elseif($className=='class2'){
            include "../".$className.".class.php";
        }elseif($className=='class3'){
            include "./".$className.".class.php";
        }
    }
    
    $p=new Person;

    四、类型约束

      1)类型约束可以使用数组约束和类名约束

      2)数组约束:只需要在方法或函数的参数前加入array关键字即可

      3)类名约束:只需要在方法或函数的参数前加入类名,表示调用时必须传递该类的对象或该类的子类的对象

    class Person1{
        function say(array $info){  //数组约束
            echo "P1:".join(',',$info);
        }
    }
    
    class Person2{
        function say(array $info){  //数组约束
            echo "P2:".join(',',$info);
        }
    }
    
    class Person{
        function test(Person1 $obj){  //类名约束
            $obj->say(array('abc','ABC'));
        }
    }
    
    $p=new Person;
    $p->test(new Person1);
  • 相关阅读:
    UVA 10003:Cutting Sticks 区间DP
    UVAlive 10154:Dire Wolf 区间DP
    HDU 5071:Chat(2014 Asia AnShan Regional Contest)
    HDU 5074:Hatsune Miku(2014 Asia AnShan Regional Contest)
    android 代码混淆及问题大集锦
    android调试bug集锦 onActivityResult立即返回,并且被CANCEL
    开启g++ 编辑器 c++11特性
    解析最简单的验证码
    将图片文件转换为.py文件
    使用pyinstaller 2.1将python打包并添加版本信息和图标
  • 原文地址:https://www.cnblogs.com/zhouwanqiu/p/9588757.html
Copyright © 2011-2022 走看看