首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> PHP 程式設計 >> PHP 綜合知識

PHP 介面與抽象類深度解析:異同、應用場景與代碼實戰

     編輯:PHP 綜合知識

PHP 介面 vs 抽象類:核心差異與選擇指南

介面與抽象類都是實現多型與規範契約的工具,但設計意圖、語法限制、適用場景有本質不同。本文深度解析兩者異同並提供選擇決策指南。

一、抽象類

定義特徵

  • 使用 abstract class 宣告
  • 可包含抽象方法(無方法體,子類必須實作)與具體方法(有預設實作)
  • 可定義屬性(public/protected/private)、常數、建構子
  • 無法直接實例化,需被繼承且實作所有抽象方法

代碼範例

<?php
abstract class Animal {
    // 屬性
    protected $name;
    protected $age = 0;
    public const TYPE = 'animal';

    // 具體方法(預設實作)
    public function breathe() {
        echo "{$this->name} 在呼吸...\n";
    }

    // 抽象方法(強制子類實作)
    abstract protected function makeSound();
    abstract public function move();
}

abstract class Mammal extends Animal {
    // 部分實作抽象方法
    public function makeSound() {
        echo "哺乳類發聲...\n";
    }
    // move() 仍為抽象,Mammal 仍為抽象類
}

class Dog extends Mammal {
    public function __construct($name) {
        $this->name = $name;
    }

    // 必須實作所有剩餘抽象方法
    public function move() {
        echo "{$this->name} 用四條腿跑動\n";
    }
}

$dog = new Dog('旺財');
$dog->breathe();  // 繼承具體方法
$dog->makeSound(); // 繼承中間類實作
$dog->move();      // 自身實作

關鍵規則

  1. 子類實作抽象方法時,存取修飾子不可比父類更嚴格(protected → public ✅,public → protected ❌)
  2. 抽象方法不能宣告為 private(會報 Fatal error)
  3. 若子類未實作所有抽象方法,該子類也必須宣告為 abstract

二、介面

定義特徵

  • 使用 interface 宣告
  • 完全抽象:只能宣告方法(預設 public)、常數
  • 不能定義屬性、建構子、方法體
  • 類別使用 implements 實作介面
  • 一個類別可實作多個介面,但只能繼承一個父類

代碼範例

<?php
interface Flyable {
    public const MAX_HEIGHT = 10000;
    public function fly();
    public function land();
}

interface Swimmable {
    public function swim();
}

class Duck implements Flyable, Swimmable {
    public function fly() {
        echo "鴨子飛行中... (高度 < " . Flyable::MAX_HEIGHT . "m)\n";
    }
    public function land() { echo "鴨子降落\n"; }
    public function swim() { echo "鴨子游泳\n"; }
}

// 介面可繼承多個介面
interface FlyableAndSwimmable extends Flyable, Swimmable {}

三、異同對照表

特性抽象類介面
關鍵字extendsimplements
多重實作單一繼承可實作多個
方法類型抽象 + 具體全部抽象 (PHP 8.0 前)
屬性/狀態✅ 可定義❌ 僅常數
建構子✅ 可定義❌ 不可
存取修飾子public/protected/private僅 public
設計意圖「是一種」關係、共享代碼/狀態「能做某事」能力、契約規範

四、PHP 8.0+ 新特性:介面預設實作

<?php
interface Logger {
    public function log(string $message);
    
    // PHP 8.0+ 介面可有預設方法實作
    public function logInfo(string $message) {
        $this->log("[INFO] $message");
    }
    
    public function logError(string $message) {
        $this->log("[ERROR] $message");
    }
}

五、選擇決策指南

使用抽象類當:

  • 需要共享代碼/狀態(屬性、建構子、預設方法)
  • 建立「是一種」關係(Dog 是 Animal)
  • 需要非 public 的抽象方法
  • 需要定義建構子強制初始化邏輯

使用介面當:

  • 定義「能做某事」的能力契約
  • 類別需要實作多個不相關契約
  • 無需共享狀態,純行為規範
  • 第三方庫擴展(不想強制繼承特定基類)

組合使用: 抽象類實作介面,子類繼承抽象類

六、實戰範例:支付系統

<?php
// 契約:支付能力
interface Payable {
    public function pay(float $amount): bool;
    public function refund(string $transactionId): bool;
}

// 共享邏輯:記錄、驗證
abstract class BasePayment implements Payable {
    protected $logger;
    protected $config;

    public function __construct(Logger $logger, array $config) {
        $this->logger = $logger;
        $this->config = $config;
    }

    // 模板方法:共享流程
    public function pay(float $amount): bool {
        if (!$this->validateAmount($amount)) return false;
        $result = $this->doPay($amount);
        $this->logger->log("Payment {$result ? 'success' : 'failed'}: $amount");
        return $result;
    }

    abstract protected function doPay(float $amount): bool;
    abstract protected function validateAmount(float $amount): bool;
}

// 具體實作
class AlipayPayment extends BasePayment {
    protected function doPay(float $amount): bool { /* ... */ }
    protected function validateAmount(float $amount): bool { /* ... */ }
}

class WechatPayment extends BasePayment {
    protected function doPay(float $amount): bool { /* ... */ }
    protected function validateAmount(float $amount): bool { /* ... */ }
}
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved