PHP的抽象类和接口类有什么区别

抽象类(abstract class)和接口(interface)是 PHP 中实现面向对象编程的两种重要工具,它们之间有许多相似之处,但也有很多关键区别。以下是它们的主要区别:

1. 定义和使用方式

抽象类(abstract class

  • 定义:抽象类是一个不能实例化的类,它可以包含部分方法实现(具体方法)和抽象方法(没有实现的方法)。抽象类的目的是为其他类提供基础功能和公共实现。
  • 继承:一个类只能继承一个抽象类。
  • 方法:抽象类可以包含具体的方法(有实现的方法)和抽象的方法(没有实现的方法)。

接口(interface

  • 定义:接口是一种特殊的抽象类,所有的方法默认没有实现,接口只定义方法签名。接口的目的是为了规定一组行为,类通过实现接口来承诺遵循这些行为。
  • 实现:类实现接口,必须实现接口中定义的所有方法。
  • 方法:接口中的所有方法默认是没有实现的(只声明没有方法体),只能声明方法的签名。

2. 方法实现

抽象类(abstract class

  • 抽象类可以有部分实现。它可以包含已经实现的方法,也可以有抽象方法,抽象方法没有实现,需要由继承的类来实现。

    abstract class Animal {
        // 已实现的方法
        public function breathe() {
            echo "Breathing...\n";
        }
    
        // 抽象方法
        abstract public function makeSound();
    }
    
    class Dog extends Animal {
        public function makeSound() {
            echo "Bark!\n";
        }
    }
    

接口(interface

  • 接口中的所有方法默认没有实现,接口只声明方法签名,类必须实现接口中的所有方法。

    interface Animal {
        public function makeSound();
    }
    
    class Dog implements Animal {
        public function makeSound() {
            echo "Bark!\n";
        }
    }
    

3. 属性

抽象类(abstract class

  • 抽象类可以有属性(成员变量),可以定义它们的类型、访问修饰符(publicprotectedprivate)以及默认值。

    abstract class Animal {
        protected $name;
        public $species;
    }
    

接口(interface

  • 接口不能有属性,只能定义常量。

    interface Animal {
        const LEGS = 4;
    }
    

4. 构造函数

抽象类(abstract class

  • 抽象类可以有构造函数,构造函数可以在父类中实现,并且可以被子类继承和调用。

    abstract class Animal {
        protected $name;
    
        public function __construct($name) {
            $this->name = $name;
        }
    }
    

接口(interface

  • 接口不能有构造函数,接口只定义方法,不关心实现细节。

    interface Animal {
        public function __construct($name); // 接口中的构造函数声明(但不能实现)
    }
    

5. 继承/实现

抽象类(abstract class

  • PHP 支持单继承,即一个类只能继承一个抽象类。
  • 抽象类可以继承其他类,也可以实现接口。

接口(interface

  • PHP 支持多实现,即一个类可以实现多个接口。

  • 接口不能继承其他类,但可以继承多个接口。

    interface Animal {
        public function makeSound();
    }
    
    interface Mammal {
        public function giveBirth();
    }
    
    class Dog implements Animal, Mammal {
        public function makeSound() {
            echo "Bark!\n";
        }
    
        public function giveBirth() {
            echo "Giving birth to puppies\n";
        }
    }
    

6. 访问修饰符

抽象类(abstract class

  • 抽象类中的方法可以使用不同的访问修饰符(publicprotectedprivate)。你可以控制方法的访问范围。

接口(interface

  • 接口中的方法默认是public,不能使用其他访问修饰符。接口中的方法必须是公开的。

7. 使用场景

抽象类(abstract class

  • 用于共享部分代码:如果多个类有一些公共的实现,且这些类之间有继承关系,可以使用抽象类提供基础实现。抽象类适合用来描述一些具有共性的类,并将通用行为和属性提取到基类中。
  • 当类之间有层次关系(如父子类关系)时,抽象类是一个不错的选择。

接口(interface

  • 用于规范行为:接口适用于不同的类需要实现相同的行为,但这些类之间并不一定存在继承关系。接口关注的是类的行为,而不是实现细节。
  • 当类之间没有直接的继承关系时,使用接口更合适,可以让多个不相关的类实现相同的行为。

8. 总结表格

特性 抽象类(abstract class 接口(interface
方法实现 可以有部分实现(有实现的方法和抽象方法) 只有方法声明,没有实现,类必须实现所有方法
属性 可以有属性(成员变量) 不能有属性,只有常量
构造函数 可以有构造函数 不能有构造函数
继承/实现 只能继承一个抽象类 可以实现多个接口
访问修饰符 可以使用 publicprotectedprivate 修饰符 所有方法默认为 public
使用场景 适合共享代码和有继承关系的类 适合定义行为规范,多个不相关类实现相同行为
灵活性 较低,单继承 高,支持多继承

总结

  • 抽象类:适用于需要共享部分实现的类之间的继承关系,允许定义部分方法的实现和属性。
  • 接口:适用于不相关的类之间共享行为的场景,强调类的行为契约而非实现细节,支持多继承。

两者的使用场景和目的不同,理解它们的区别和用途可以帮助我们在开发过程中做出更合适的设计选择。

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《G01 Go 实战入门》
从零开始带你一步步开发一个 Go 博客项目,让你在最短的时间内学会使用 Go 进行编码。项目结构很大程度上参考了 Laravel。
讨论数量: 0
(= ̄ω ̄=)··· 暂无内容!

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!