PHP - 面向对象编程/OOP

本文深入探讨了PHP面向对象编程(OOP)的核心概念及其在开发高性能程序中的应用。重点解析了静态(static)关键字的功能及newself()与newstatic()在继承场景下的差异,帮助读者理解并掌握PHP OOP的关键细节。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.应用场景

熟练掌握PHP面向对象编程, 开发高质量高性能程序.

2.学习/操作

1. 文档

OOP 面向对象编程_穿素白衫的少年的博客-CSDN博客

PHP: 静态(static)关键字 - Manual  //Static(静态)关键字 ¶

new self() 和 new static() 的区别_Yee Jason的博客-CSDN博客_new static  //new self() 和 new static() 的区别

AI问答! -- 推荐

2. 整理输出

PHP 中的多态与面向对象三大特性

在 PHP 面向对象编程中,确实有三大核心特性:封装、继承和多态。您提到的"抽象"实际上是封装的一种表现形式。

一、PHP 类的三大特性

1. 封装 (Encapsulation)

  • 定义:隐藏对象内部实现细节,仅暴露必要接口
  • 实现方式:
  • 访问修饰符:publicprotectedprivate
  • Getter/Setter 方法
  • 接口与抽象类
class BankAccount {
    private $balance = 0;
    
    public function deposit($amount) {
        $this->balance += $amount;
    }
    
    public function getBalance() {
        return $this->balance;
    }
}

2. 继承 (Inheritance)

  • 定义:子类继承父类的属性和方法
  • 特点:
  • 代码复用
  • extends 关键字实现
  • 单继承(PHP不支持多重继承)
class Animal {
    public function makeSound() {
        return "Some generic sound";
    }
}

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

3. 多态 (Polymorphism)

  • 定义:不同类的对象对同一消息做出不同响应
  • 两种形式:
  • 编译时多态(方法重载,PHP不支持)
  • 运行时多态(方法重写和接口实现)

二、PHP 多态行为详解

1. 方法重写(子类覆盖父类方法)

class Shape {
    public function draw() {
        echo "Drawing a generic shape\n";
    }
}

class Circle extends Shape {
    public function draw() {
        echo "Drawing a circle\n";
    }
}

$shape = new Circle();
$shape->draw(); // 输出: Drawing a circle

2. 接口实现多态

interface PaymentGateway {
    public function processPayment($amount);
}

class PayPal implements PaymentGateway {
    public function processPayment($amount) {
        echo "Processing PayPal payment for $amount\n";
    }
}

class Stripe implements PaymentGateway {
    public function processPayment($amount) {
        echo "Processing Stripe payment for $amount\n";
    }
}

function checkout(PaymentGateway $gateway, $amount) {
    $gateway->processPayment($amount);
}

checkout(new PayPal(), 100);  // 处理PayPal支付
checkout(new Stripe(), 200);  // 处理Stripe支付

3. 抽象类实现多态

abstract class DatabaseDriver {
    abstract public function connect();
    
    public function testConnection() {
        $this->connect();
        echo "Connection successful\n";
    }
}

class MySQLDriver extends DatabaseDriver {
    public function connect() {
        echo "Connecting to MySQL...\n";
    }
}

class PostgreSQLDriver extends DatabaseDriver {
    public function connect() {
        echo "Connecting to PostgreSQL...\n";
    }
}

$db = new MySQLDriver();
$db->testConnection(); // 输出连接MySQL的信息

4. 后期静态绑定(static 关键字)

class ParentClass {
    public static function getClass() {
        return static::class; // 多态行为
    }
}

class ChildClass extends ParentClass {}

echo ChildClass::getClass(); // 输出 "ChildClass"

三、多态在 PHP 中的实际应用

1. Laravel 的服务容器

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

class FileLogger implements LoggerInterface {
    public function log($message) {
        file_put_contents('app.log', $message);
    }
}

class Controller {
    protected $logger;
    
    public function __construct(LoggerInterface $logger) {
        $this->logger = $logger; // 可以接收任何LoggerInterface实现
    }
}

2. 策略模式

interface SortStrategy {
    public function sort(array $data): array;
}

class BubbleSort implements SortStrategy {
    public function sort(array $data): array {
        // 实现冒泡排序
        return $sortedData;
    }
}

class QuickSort implements SortStrategy {
    public function sort(array $data): array {
        // 实现快速排序
        return $sortedData;
    }
}

class Sorter {
    private $strategy;
    
    public function __construct(SortStrategy $strategy) {
        $this->strategy = $strategy;
    }
    
    public function sortData(array $data) {
        return $this->strategy->sort($data);
    }
}

3. 工厂模式结合多态

interface Vehicle {
    public function drive();
}

class Car implements Vehicle {
    public function drive() {
        echo "Driving a car\n";
    }
}

class Truck implements Vehicle {
    public function drive() {
        echo "Driving a truck\n";
    }
}

class VehicleFactory {
    public static function create($type): Vehicle {
        return match ($type) {
            'car' => new Car(),
            'truck' => new Truck(),
            default => throw new InvalidArgumentException("Unknown vehicle type"),
        };
    }
}

$vehicle = VehicleFactory::create('car');
$vehicle->drive(); // Driving a car

四、PHP 多态的特点

  • 鸭子类型:PHP 是弱类型语言,"如果它走起路来像鸭子,叫起来像鸭子,那么它就是鸭子"
  • 接口与类型提示:通过接口和类型提示实现强多态
  • 灵活性:允许运行时决定对象的具体行为
  • 扩展性:易于添加新类而不修改现有代码

五、与其他语言的对比

特性

PHP

Java

C++

编译时多态

不支持

方法重载

函数重载

运行时多态

支持

支持

支持

多重继承

不支持

不支持

支持

接口多继承

支持

支持

不支持

总结

PHP 的多态主要通过:

  • 方法重写(子类覆盖父类方法)
  • 接口实现(不同类实现相同接口)
  • 抽象类继承(抽象方法强制子类实现)
  • 类型提示(参数类型约束)

多态使代码更加灵活、可扩展和可维护,是面向对象设计中最重要的概念之一。

鸭子类型(Duck Typing)在PHP中的详细解释

鸭子类型是一种动态类型的概念,源自James Whitcomb Riley的名言:"当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。"

核心概念

在编程中,鸭子类型意味着:

  • 不关注对象的类型本身
  • 只关注对象能否执行特定操作
  • 如果一个对象有我们需要的方法和属性,我们就可以像使用目标类型一样使用它

PHP中的鸭子类型特点

  • 弱类型系统:PHP不强制要求变量类型
  • 运行时检查:方法/属性是否存在在运行时确定
  • 接口非必须:即使没有明确实现接口,只要对象有相应方法就能工作

示例说明

示例1:基础鸭子类型

class Duck {
    public function quack() {
        echo "Quack!\n";
    }
    
    public function fly() {
        echo "I'm flying!\n";
    }
}

class Person {
    public function quack() {
        echo "I'm pretending to be a duck!\n";
    }
    
    public function fly() {
        echo "I'm on an airplane!\n";
    }
}

function makeItQuack($duckLikeObject) {
    $duckLikeObject->quack();
}

makeItQuack(new Duck());  // 输出: Quack!
makeItQuack(new Person()); // 输出: I'm pretending to be a duck!

分析:

  • makeItQuack函数不检查参数类型
  • 只要对象有quack()方法就能工作
  • Person不是鸭子,但可以"像鸭子一样叫"

示例2:实际应用场景

class FileLogger {
    public function write($message) {
        file_put_contents('app.log', $message, FILE_APPEND);
    }
}

class DatabaseLogger {
    public function write($message) {
        DB::insert('logs', ['message' => $message]);
    }
}

function logMessage($logger, $message) {
    $logger->write($message);
}

logMessage(new FileLogger(), "Error occurred");      // 写入文件
logMessage(new DatabaseLogger(), "Error occurred");  // 写入数据库

优势:

  • 不需要共同接口
  • 不需要继承关系
  • 只要都有write()方法就能工作

示例3:与接口的对比

// 接口方式
interface LoggerInterface {
    public function write($message);
}

class FileLogger implements LoggerInterface { /*...*/ }
class DBLogger implements LoggerInterface { /*...*/ }

// 鸭子类型方式
// 不需要实现接口,只要有write方法就行
class EmailLogger {
    public function write($message) {
        mail('admin@test.com', 'Error', $message);
    }
}

function logError($logger, $message) {
    $logger->write($message);
}

logError(new EmailLogger(), "Something broke"); // 正常工作

鸭子类型的优缺点

优点

  • 灵活性:不需要严格的类型层次结构
  • 简洁性:减少接口和抽象类的使用
  • 快速原型:易于快速开发和测试
  • 动态性:运行时决定行为

缺点

  • 安全性:缺乏编译时类型检查
  • 可读性:难以从代码直接看出预期接口
  • 维护性:修改时可能破坏依赖该对象的代码
  • IDE支持:自动完成和重构工具支持较差

PHP中的最佳实践

  • 文档注释:用@method@property标注预期行为
/**
 * @method void quack() 应该实现鸭子叫声
 * @method void fly() 应该实现飞行能力
 */
function makeItQuack($duckLikeObject) {
    $duckLikeObject->quack();
}
  • 防御性编程:使用检查
function makeItQuack($duckLikeObject) {
    if (!method_exists($duckLikeObject, 'quack')) {
        throw new InvalidArgumentException('对象必须实现quack方法');
    }
    $duckLikeObject->quack();
}
  • 渐进式类型:PHP 7+可用类型提示但保持灵活性
function makeItQuack(object $duckLikeObject) {
    if (!method_exists($duckLikeObject, 'quack')) {
        throw new InvalidArgumentException('对象必须实现quack方法');
    }
    $duckLikeObject->quack();
}

与接口的对比

特性

鸭子类型

接口

类型安全

运行时检查

编译时检查

耦合度

明确性

隐式约定

显式契约

灵活性

重构难度

困难

容易

IDE支持

有限

良好

实际框架中的应用

Laravel 集合的鸭子类型

// 任何实现了可遍历方法的对象都能被collect()包装
$collection = collect(new ArrayObject([1, 2, 3]));

// 因为ArrayObject实现了所需的遍历方法

Mock对象测试

// 创建测试用的鸭子类型对象
$mockUser = new class {
    public function getId() { return 1; }
    public function getName() { return 'Test'; }
};

// 即使没有实现User接口也能工作
$userService->process($mockUser);

总结

鸭子类型在PHP中表现为:

  • 关注行为而非类型
  • 动态检查方法/属性是否存在
  • 提高代码灵活性但降低安全性
  • 适合快速原型和小型项目
  • 大型项目中建议结合接口使用

理解鸭子类型有助于更好地利用PHP的动态特性,但也需要注意其潜在风险。

在团队开发或大型项目中,通常建议使用接口来获得更好的可维护性,而在脚本或快速开发中可以充分利用鸭子类型的灵活性。

后续整理补充

...

3.问题/补充

1. new self() 和 new static() 的区别

他们的区别:

只有在继承中才能体现出来、如果没有任何继承、那么二者没有任何区别

然后 new self() 返回的实列是不会变的,无论谁去调用,都返回的一个类的实列(方法的定义者),
而 new static则是由调用者决定的.

后续补充

...

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值