• PHP面向对象程序设计之抽象类和抽象方法


    抽象类:

    抽象类不能被实例化。抽象类中只定义(或部分实现)子类需要的方法。子类可以继承它并且通过实现其中的抽象方法,使抽象类具体化。

    我们可以用一个abstract关键字来定义一个抽象类,示例如下:

    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }

    抽象类的特性:

    1)、定义为抽象的类不能被实例化。

    抽象类和普通类一样,都可以创建方法和属性,那么抽象类可以像普通类那样被实例化吗?

    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }
    
    $Animal = new Animal();

    运行结果:Fatal error: Cannot instantiate abstract class Animal in D:phpStudyWWWdemoabstract.php on line 15

    运行结果显示,不能实例化抽象类Animal,现在知道咯,抽象类不能像普通类那样被实例化的哟。

    2)、如果它里面至少有一个方法是被声明为抽象的,那么这个类就必须被声明为抽象的。

    抽象方法用abstract关键字声明,其中不能有具体内容。你可以像声明普通类方法那样声明抽象方法,但要以分号而不是方法体结束。而在大多数情况下,抽象类中至少要有一个抽象方法,否则这个抽象类也就没有抽象的意义了,也就是说,这个抽象类内可以没有抽象方法只有普通方法,但是,你也没必要将这个类声明称抽象类了,直接去掉abstract变成普通类就行了。

    <?php
    
    class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }

    运行结果:Fatal error: Class Animal contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Animal::barking) in D:phpStudyWWWdemoabstract.php on line 13

    结果显示了一个致命的错误,说类Animal包含了一个抽象方法,所以这个类必须被声明为抽象类或者实现有抽象方法setit()的类。

    3)、被定义为抽象的方法只是声明了其调用方式(参数),不能定义其具体的功能实现。

    4)、继承一个抽象类的时候,子类必须定义父类中的所有抽象方法(这些方法的访问控制必须和父类中一样(或者更为宽松)。)

    创建抽象方法后,要确保所有子类中都实现可该方法,但实现的细节可以先不确定。

    如果创建了一个继承自抽象类Animal的普通类,但是不实现其中的抽象方法,会发生什么呢?

    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }
    
    class Fish extends Animal{
        
    }

    运行结果:Fatal error: Class Fish contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Animal::barking) in D:phpStudyWWWdemoabstract.php on line 17

    这个和只有抽象方法没有把类定义为抽象类发生的错误一样,所以抽象类的每个子类必须实现抽象类中的所有抽象方法,或者把他们自身也声明为抽象方法。

    扩展类不仅仅负责简单实现抽象类中的抽象方法,还必须重新声明方法。新的方法的访问控制不能比抽象方法的访问控制更严格。新的实现方法的参数个数应该和抽象方法的参数个数一样,重新生成对应的类型提示。

    1> 验证:新的实现方法的参数个数应该和抽象方法的参数个数一样

    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }
    
    class Fish extends Animal{
        public function setit($name){
            echo $name;
        }
    }

    运行代码:Fatal error: Declaration of Fish::setit() must be compatible with Animal::setit() in D:phpStudyWWWdemoabstract.php on line 19

    2> 验证:新的方法的访问控制不能比抽象方法的访问控制更严格

    (1) 如果 Animal 中 setit() 声明为 public ,那么 Fish 中 setit() 的声明只能是 public ,不能是 protected 或 private ;
    (2) 如果 Animal 中 setit() 声明为 protected ,那么 Fish 中 setit() 的声明可以是 public 或 protected ,但不能是 private ;
    (3) 如果 Animal 中 setit() 声明为 private ,嘿嘿,不能定义为 private 哦!

    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }
    
    class Fish extends Animal{
        private function setit(){
    
        }
    }

    运行结果:Fatal error: Access level to Fish::setit() must be public (as in class Animal) in D:phpStudyWWWdemoabstract.php on line 19

    5)、子类可以定义一个可选参数(也就是必须要有默认值),而父类抽象方法的声明里没有,则两者的声明并无冲突。

    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit($name);
    }
    
    class Fish extends Animal{
        public function setit($name,$separator = ''){
    
        }
    }

    6)、一个抽象类继承另一个抽象类时,抽象方法不需要声明为抽象的

    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }
    //错误代码
    abstract class Fish extends Animal{
        abstract public function setit();
    }
    <?php
    
    abstract class Animal{
        //抽象类中可以定义属性
        protected $animal = 'animal';
        //抽象类中也可以定义非抽象方法
        public function printit($name){
            $this->animal = $name;
            echo $this->animal;
        }
        //抽象方法
        abstract public function setit();
    }
    //继承抽象类时,抽象方法不需要声明抽象
    abstract class Fish extends Animal{
        
    }

     从PHP 5.2开始,不再允许同时使用abstract static 修饰一个抽象类的抽象方法。也就是说,PHP不再支持抽象静态方法,继续使用,将导致E_STRICT错误。

  • 相关阅读:
    P3822 [NOI2017]整数
    P4630 [APIO2018] Duathlon 铁人两项
    P3230 [HNOI2013]比赛
    P2570 [ZJOI2010]贪吃的老鼠
    P4576 [CQOI2013]棋盘游戏
    P3256 [JLOI2013]赛车
    P3297 [SDOI2013]逃考
    CF487E Tourists
    设置一个双色球脚本(2)并带颜色输出
    设置一个双色球脚本
  • 原文地址:https://www.cnblogs.com/zhouguowei/p/9354621.html
Copyright © 2020-2023  润新知