Deprecated: parse_url(): Passing null to parameter #1 ($url) of type string is deprecated in /www/wwwroot/blog_qqvbc_com/usr/plugins/Access/Access_Core.php on line 339

Deprecated: parse_url(): Passing null to parameter #1 ($url) of type string is deprecated in /www/wwwroot/blog_qqvbc_com/usr/plugins/Access/Access_Core.php on line 392

Deprecated: parse_url(): Passing null to parameter #1 ($url) of type string is deprecated in /www/wwwroot/blog_qqvbc_com/usr/plugins/Access/Access_Core.php on line 394
abstract 抽象类与接口类(PHP) - Joyber 的博客

abstract 抽象类(PHP)

作用

  1. 约束子类必须实现指定方法:抽象方法只有声明、没有实现,子类继承后必须重写这个抽象方法,否则子类也得标记为 abstract,不能实例化。用来统一接口规范。
  2. 可以放通用共用代码:和接口 interface 不一样,抽象类里面可以写已经实现好的普通方法、属性,子类直接复用。
  3. 本身不能 new 实例,只能被继承,用来做基类、模板骨架(模板方法模式非常常用)。

对比一句话:

  • interface:全部都是契约,不能写实现,一个类可以多实现
  • abstract class:一半契约(abstract方法)+一半现成代码,只能单继承

写法规则(PHP)

  1. 类前面加 abstract
  2. 抽象方法:前面 abstract,没有函数体,以分号结尾,不能有 {}
  3. 普通方法、属性、常量正常写,随便写实现
  4. 子类 extends 抽象类,必须全部实现父类所有抽象方法
  5. 抽象类不能 new

最简示例

<?php
abstract class CarrierBase
{
    // 抽象方法:子类必须实现
    abstract public function sendOrder(array $orderData): bool;
    abstract public function cancelOrder(int $orderId): bool;

    // 已经实现的公共方法,子类直接继承复用
    protected function log(string $msg): void
    {
        echo date('Y-m-d H:i:s') . ' ' . $msg . PHP_EOL;
    }
}

// 子类实现抽象类
class SelfCourierCarrier extends CarrierBase
{
    public function sendOrder(array $orderData): bool
    {
        $this->log('自有骑手接单:' . $orderData['id']);
        return true;
    }

    public function cancelOrder(int $orderId): bool
    {
        $this->log('自有骑手取消订单:' . $orderId);
        return true;
    }
}

// $base = new CarrierBase(); // 报错!抽象类不能实例化
$carrier = new SelfCourierCarrier();
$carrier->sendOrder(['id' => 1001]);

结合你上面跑腿运力场景的例子(贴合你的 CarrierInterface)

你现在是 CarrierInterface 接口;如果很多运力都共用一套日志、组装请求的逻辑,就适合改成抽象基类:

abstract class AbstractCarrier implements CarrierInterface
{
    // 公共通用能力,所有运力复用
    protected function buildOrderParam(array $raw): array
    {
        return [
            'order_no' => $raw['order_sn'],
            'addr_from' => $raw['from_address'],
            'addr_to' => $raw['to_address'],
        ];
    }
}

class SelfCourierCarrier extends AbstractCarrier
{
    public function dispatch(array $order): bool
    {
        $param = $this->buildOrderParam($order);
        // 自有骑手分发逻辑
        return true;
    }
}

class ThirdPartyCarrier extends AbstractCarrier
{
    public function dispatch(array $order): bool
    {
        $param = $this->buildOrderParam($order);
        // 调用UU/闪送接口
        return true;
    }
}

重点坑点

  1. 抽象方法不能写body:abstract public func(); ✅,带大括号 ❌
  2. 子类实现的方法,访问权限不能比父抽象方法更严格(父public,子类不能改成protected/private)
  3. 抽象类可以没有任何抽象方法(可以,但意义不大,仅用来禁止直接new基类)
  4. 一个类只能继承一个抽象类(PHP单继承)

什么时候选 abstract,什么时候选 interface

  • 多个子类有大量重复共用代码 → abstract 抽象类
  • 只定义调用契约、没有公共逻辑、一个类需要多套契约 → interface

标签: none

添加新评论