带你了解abstract和interface的区别

/**
 * 作者:xianhenyuan
 * 关于作者:公号【会飞的老司机】、网络项目【798项目矩阵】主理人。
 */

interface接口类

用一个常见的CRUD的例子来感受下 interface接口类

    /**
     * 数据库方法模板
     * Interface SQLMethodsInterface
     */
    interface SQLMethodsInterface{
        public function insert();
        public function delete();
        public function save();
        public function select();
    }
    /**
     * 扩展的前置操作,用来后面体现多继承
     * Interface BeforeInterface
     */
    interface BeforeInterface{
        function beforeAction();
    }

如上 方法模板 的代码,interface 用来描述一个类或者多个类的共同行为
当下面的子类继承的时候,也可同时继承多个 interface,但必须实现所有被继承的 interface 中定义的所有方法(约束的作用)。
也就是说如果你属于这个类,就必须遵守我的规矩,实现我的定义,具体怎么实现我就不管了。
用代码来感受下:

    /**
     * 同时继承并实现 SQLMethodsInterface、BeforeInterface
     * Class XXXDbClass
     */
    class XXXDbClass implements SQLMethodsInterface,BeforeInterface
    {

        function __construct()
        {
            echo '<pre/>';
            $this->beforeAction();
        }

        function beforeAction()
        {
            var_dump('我是 beforeAction 方法');
        }

        function insert()
        {
            var_dump('我是 insert 方法');
        }

        function delete()
        {
            var_dump('我是 delete 方法');
        }

        function save()
        {
            var_dump('我是 save 方法');
        }

        function select()
        {
            var_dump('我是 select 方法');
        }

    }

看到这里你可能就会有疑问了,为什么 interface 不实现这些共同的行为呢?
其目的是为了解耦
用代码来感受下:

    /***
     * Class MyClass
     */
    class  MyClass{

        private $SQLInterface = null;

        public function __construct(SQLMethodsInterface $SQLInterface)
        {
            $this->SQLInterface = $SQLInterface;
        }

        public function select(){
            $this->SQLInterface->select();
        }
    }
    $MyClassObject = new MyClass(new XXXDbClass());
    $MyClassObject->select();

如果在 MyClass 中使用到了数据库存储,这时只需要将 SQLMethodsInterface接口 注入到 MyClass 中即可。
后续如果需要调整为其他类型的数据库存储,MyClass 的代码是不需要做任何改动的。

abstract抽象类

当你发现一个方法的代码在一个类或者多个类重复写的时候,就可以考虑用抽象类来实现它了。
上面这句话可能会给你带来疑问,公共的方法我写在一个公共类里,谁用谁继承不就好了嘛,干嘛还要用抽象类?
这个问题来说说抽象类的另外一个好处:约束
抽象类给我的感觉有点像是对于接口类的一个补充,某些角度上跟接口类很像,子类在继承的时候必须定义或实现其父类的所有抽象方法
这样的约束省去了我们编写公共类之后还要再去定义一个接口类(继承了公共类,子类没去继承和实现接口怎么办?)
用代码来感受下:

    <?php

    /**
     * Class AbstractDemoClass
     */
    abstract class AbstractDemoClass{

        private $age;

        public function setAge($age){
            $this->age = $age;
        }


        public function getAge(){
            return $this->age;
        }

        abstract function checkAge();

    }


    /**
     * 继承的子类必须实现checkAge方法
     * Class XXXStandardClass
     */
    class  XXXStandardClass extends AbstractDemoClass{

        const ageMax = 60;
        const ageMin = 50;

        public function checkAge()
        {
            if ($this->getAge() < self::ageMin || $this->getAge() > self::ageMax){
                return '年龄不合适';
            }

            return '完美';
        }
    }



    $XXXStandardClassObject = new XXXStandardClass();
    $XXXStandardClassObject->setAge(25);
    echo $XXXStandardClassObject->checkAge();

接口类和抽象类各自的特点

interface的特点:
  • interface接口不能被实例化。
  • 子类使用 implements 继承。
  • 子类必须实现继承的interface中定义的所有方法。
  • interface接口的方法只需声明,不能定义其具体的实现,且访问控制只能被定义为 public(不能用private、protected修饰符)。
  • interface接口类中不能定义属性。
  • 子类通过 implements 继承 interface接口,同时必须实现interface接口类中定义的所有方法。
  • 子类可以继承多个interface接口。
abstract的特点:
  • abstract抽象类不能被实例化。
  • 抽象类只能被继承,使用 extends(子类只能继承一个父类)。
  • 当一个类里面如果存在一个抽象方法那么这个类必须被定义为抽象类。
  • 被定义为abstract抽象的方法只需声明调用方式,不能定义其具体的实现。
  • abstract抽象方法的访问控制不能被定义为私有(private),只能被定义为 protectedpublic
  • abstract抽象类中可以定义属性。
  • 子类继承一个抽象类的时候,必须定义或实现其父类的所有抽象方法,所有方法的访问控制必须和父类保持一直或者更为宽松。
  • 可以在子类中定义父类方法中不存在的可选参数,但是新增的不存在的参数要有默认值。

总结

interface 用来描述一个类或者多个类的共同行为,约束了子类必须实现其定义的方法
换言之,当需要保证所有开发人员都遵守一套规则的时候,可以考虑使用 interface 定义;

abstract 也可用来描述一个类或者多个类的共同行为,约束了子类必须定义或实现其定义的抽象方法。同时可以在抽象类中提供一些编写好的方法供子类复用,还可以定义类属性
换言之,在保证约束的同时还需要提供一些编写好的公共方法时,或者需要定义类属性时,可以使用 abstract 来定义。

总的来看抽象类也好,接口类也罢
其目的是为了更好的约束、复用,减少编写重复代码的无用功

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值