0
点赞
收藏
分享

微信扫一扫

PHP面向对象进阶:抽象类、接口与类型声明

ITWYY 07-17 09:00 阅读 5

引言

在PHP面向对象编程中,抽象类、接口和类型声明是构建可扩展、可维护应用程序的重要工具。本文将深入探讨这些概念,展示它们如何帮助开发者创建更健壮的代码结构。

抽象类(Abstract Classes)

抽象类是不能被实例化的类,它定义了子类必须实现的方法模板。

基本抽象类示例

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

class Dog extends Animal {
    public function makeSound() {
        return "Woof! Woof!";
    }
}

class Cat extends Animal {
    public function makeSound() {
        return "Meow!";
    }
}

$dog = new Dog("Buddy");
$cat = new Cat("Whiskers");

echo $dog->getName() . " says: " . $dog->makeSound() . "\n";
// 输出: Buddy says: Woof! Woof!

echo $cat->getName() . " says: " . $cat->makeSound() . "\n";
// 输出: Whiskers says: Meow!

抽象类的高级用法

abstract class Shape {
    abstract public function area();
    abstract public function perimeter();
    
    public function compareArea(Shape $otherShape) {
        return $this->area() <=> $otherShape->area();
    }
    
    public function __toString() {
        return get_class($this) . " - Area: " . $this->area() . 
               ", Perimeter: " . $this->perimeter();
    }
}

class Rectangle extends Shape {
    private $width;
    private $height;
    
    public function __construct($width, $height) {
        $this->width = $width;
        $this->height = $height;
    }
    
    public function area() {
        return $this->width * $this->height;
    }
    
    public function perimeter() {
        return 2 * ($this->width + $this->height);
    }
}

class Circle extends Shape {
    private $radius;
    
    public function __construct($radius) {
        $this->radius = $radius;
    }
    
    public function area() {
        return pi() * pow($this->radius, 2);
    }
    
    public function perimeter() {
        return 2 * pi() * $this->radius;
    }
}

$rectangle = new Rectangle(5, 10);
$circle = new Circle(7);

echo $rectangle . "\n";
// 输出: Rectangle - Area: 50, Perimeter: 30

echo $circle . "\n";
// 输出: Circle - Area: 153.9380400259, Perimeter: 43.982297150257

$result = $rectangle->compareArea($circle);
echo $result == -1 ? "Rectangle is smaller" : ($result == 0 ? "Equal" : "Rectangle is larger");
// 输出: Rectangle is smaller

接口(Interfaces)

接口定义了一组方法契约,实现类必须遵循这些契约。

基本接口示例

interface Logger {
    public function log($message);
}

class FileLogger implements Logger {
    private $filePath;
    
    public function __construct($filePath) {
        $this->filePath = $filePath;
    }
    
    public function log($message) {
        file_put_contents($this->filePath, date('Y-m-d H:i:s') . " - " . $message . "\n", FILE_APPEND);
    }
}

class DatabaseLogger implements Logger {
    private $connection;
    
    public function __construct(PDO $connection) {
        $this->connection = $connection;
    }
    
    public function log($message) {
        $stmt = $this->connection->prepare("INSERT INTO logs (message, created_at) VALUES (?, NOW())");
        $stmt->execute([$message]);
    }
}

function processOrder(Logger $logger) {
    // 处理订单逻辑...
    $logger->log("Order processed successfully");
}

$fileLogger = new FileLogger('app.log');
$dbLogger = new DatabaseLogger(new PDO('mysql:host=localhost;dbname=test', 'user', 'password'));

processOrder($fileLogger);
processOrder($dbLogger);

接口继承与多接口实现

interface Drawable {
    public function draw();
}

interface Scalable {
    public function scale($factor);
}

interface Transformable extends Drawable, Scalable {
    public function rotate($degrees);
}

class Graphic implements Transformable {
    public function draw() {
        echo "Drawing graphic...\n";
    }
    
    public function scale($factor) {
        echo "Scaling by factor {$factor}...\n";
    }
    
    public function rotate($degrees) {
        echo "Rotating by {$degrees} degrees...\n";
    }
}

$graphic = new Graphic();
$graphic->draw();
$graphic->scale(1.5);
$graphic->rotate(45);

类型声明(Type Declarations)

PHP7+引入了更严格的类型声明系统,提高了代码的可靠性和可预测性。

标量类型声明

declare(strict_types=1); // 严格类型模式

class Calculator {
    public static function add(float $a, float $b): float {
        return $a + $b;
    }
    
    public static function concat(string $a, string $b): string {
        return $a . $b;
    }
    
    public static function isEven(int $number): bool {
        return $number % 2 === 0;
    }
}

echo Calculator::add(5.5, 3.2) . "\n"; // 输出: 8.7
echo Calculator::concat("Hello", " World") . "\n"; // 输出: Hello World
var_dump(Calculator::isEven(4)); // 输出: bool(true)

// Calculator::add("5", "3"); // 在严格模式下会抛出TypeError

返回类型声明

class UserRepository {
    private $users = [
        ['id' => 1, 'name' => 'Alice'],
        ['id' => 2, 'name' => 'Bob']
    ];
    
    public function findById(int $id): ?array {
        foreach ($this->users as $user) {
            if ($user['id'] === $id) {
                return $user;
            }
        }
        return null;
    }
    
    public function getAllNames(): array {
        return array_column($this->users, 'name');
    }
    
    public function createUser(string $name): void {
        $this->users[] = ['id' => count($this->users) + 1, 'name' => $name];
    }
}

$repo = new UserRepository();
var_dump($repo->findById(1)); // 输出用户Alice的数据
var_dump($repo->findById(99)); // 输出: NULL
print_r($repo->getAllNames()); // 输出: Array ( [0] => Alice [1] => Bob )
$repo->createUser("Charlie");

对象类型声明与接口类型提示

interface PaymentGateway {
    public function charge(float $amount): bool;
}

class CreditCardPayment implements PaymentGateway {
    public function charge(float $amount): bool {
        echo "Charging \${$amount} via Credit Card...\n";
        // 实际支付处理逻辑
        return true;
    }
}

class PayPalPayment implements PaymentGateway {
    public function charge(float $amount): bool {
        echo "Charging \${$amount} via PayPal...\n";
        // 实际支付处理逻辑
        return true;
    }
}

class PaymentProcessor {
    public function process(PaymentGateway $gateway, float $amount): bool {
        return $gateway->charge($amount);
    }
}

$processor = new PaymentProcessor();
$creditCard = new CreditCardPayment();
$paypal = new PayPalPayment();

$processor->process($creditCard, 100.50);
$processor->process($paypal, 75.25);

抽象类与接口的结合使用

abstract class DatabaseModel {
    abstract protected static function getTableName(): string;
    
    public static function all(): array {
        $table = static::getTableName();
        // 模拟数据库查询
        return "SELECT * FROM {$table}";
    }
    
    public static function find(int $id): ?array {
        $table = static::getTableName();
        // 模拟数据库查询
        return "SELECT * FROM {$table} WHERE id = {$id}";
    }
}

interface Timestampable {
    public function getCreatedAt(): DateTime;
    public function getUpdatedAt(): DateTime;
}

interface SoftDeletable {
    public function isDeleted(): bool;
    public function softDelete(): void;
}

class User extends DatabaseModel implements Timestampable, SoftDeletable {
    protected static function getTableName(): string {
        return 'users';
    }
    
    private $createdAt;
    private $updatedAt;
    private $deleted = false;
    
    public function __construct() {
        $this->createdAt = new DateTime();
        $this->updatedAt = new DateTime();
    }
    
    public function getCreatedAt(): DateTime {
        return $this->createdAt;
    }
    
    public function getUpdatedAt(): DateTime {
        return $this->updatedAt;
    }
    
    public function isDeleted(): bool {
        return $this->deleted;
    }
    
    public function softDelete(): void {
        $this->deleted = true;
        $this->updatedAt = new DateTime();
    }
}

$user = new User();
var_dump(User::all()); // 输出: string(17) "SELECT * FROM users"
var_dump($user->getCreatedAt()); // 输出当前时间
$user->softDelete();
var_dump($user->isDeleted()); // 输出: bool(true)

类型声明的高级应用:联合类型与交集类型

PHP8引入了联合类型和交集类型,进一步增强了类型系统的表达能力。

联合类型(Union Types)

class Product {
    public function calculateShippingCost(int|float $weight): float {
        if (is_int($weight)) {
            return $weight * 0.5;
        }
        return $weight * 0.75;
    }
    
    public function setDiscount(string|DateTime $discountEnd): void {
        if (is_string($discountEnd)) {
            $discountEnd = new DateTime($discountEnd);
        }
        echo "Discount ends at: " . $discountEnd->format('Y-m-d') . "\n";
    }
}

$product = new Product();
echo $product->calculateShippingCost(10) . "\n"; // 输出: 5
echo $product->calculateShippingCost(7.5) . "\n"; // 输出: 5.625

$product->setDiscount("2023-12-31");
$product->setDiscount(new DateTime("2023-06-30"));

交集类型(Intersection Types)

interface Loggable {
    public function log(string $message): void;
}

interface Cacheable {
    public function cache(string $key, $value): void;
    public function getFromCache(string $key);
}

class LoggerCache implements Loggable, Cacheable {
    private $logs = [];
    private $cache = [];
    
    public function log(string $message): void {
        $this->logs[] = $message;
    }
    
    public function cache(string $key, $value): void {
        $this->cache[$key] = $value;
    }
    
    public function getFromCache(string $key) {
        return $this->cache[$key] ?? null;
    }
    
    public function getLogs(): array {
        return $this->logs;
    }
}

function processData(Loggable&Cacheable $service, array $data): void {
    foreach ($data as $key => $value) {
        $service->cache($key, $value);
        $service->log("Cached value for key: {$key}");
    }
}

$service = new LoggerCache();
processData($service, ['name' => 'Alice', 'age' => 30]);

print_r($service->getFromCache('name')); // 输出: Alice
print_r($service->getLogs());
/* 输出:
Array
(
    [0] => Cached value for key: name
    [1] => Cached value for key: age
)
*/

结语

抽象类、接口和类型声明是PHP面向对象编程中强大的工具组合。抽象类提供了部分实现和强制子类实现特定方法的能力,接口定义了清晰的契约,而类型声明则增强了代码的可靠性和可维护性。

在实际开发中,建议:

  1. 使用接口定义行为契约
  2. 使用抽象类提供通用实现
  3. 尽可能使用类型声明来提高代码质量
  4. 在PHP8+项目中利用联合类型和交集类型简化代码

在下一篇文章中,我们将探讨PHP中的特性(Traits)、匿名类和对象比较等高级面向对象特性,这些将进一步扩展你的PHP面向对象编程能力。

举报

相关推荐

0 条评论