PHP面向对象编程深入理解
PHP的面向对象从PHP5开始走向成熟,到了PHP8已经非常完善了。封装、继承、多态这三个基本特征要理解透彻,写出来的代码质量才会高。
先说说封装。封装就是把数据和操作数据的方法绑定在一起,对外隐藏内部实现细节。PHP通过访问控制修饰符来实现封装,public、protected、private分别控制不同级别的访问权限。
```php
class BankAccount
{
private string $accountNumber;
private float $balance;
private array $transactions = [];
private bool $frozen = false;
public function __construct(string $accountNumber, float $initialBalance = 0)
{
$this->accountNumber = $accountNumber;
$this->balance = $initialBalance;
$this->logTransaction('开户', $initialBalance);
}
public function deposit(float $amount): void
{
if ($this->frozen) {
throw new RuntimeException('账户已被冻结');
}
if ($amount <= 0) {
throw new InvalidArgumentException('存款金额必须大于0');
}
$this->balance += $amount;
$this->logTransaction('存款', $amount);
}
public function withdraw(float $amount): bool
{
if ($this->frozen) {
throw new RuntimeException('账户已被冻结');
}
if ($amount <= 0) {
throw new InvalidArgumentException('取款金额必须大于0');
}
if ($amount > $this->balance) {
return false;
}
$this->balance -= $amount;
$this->logTransaction('取款', -$amount);
return true;
}
public function getBalance(): float
{
return $this->balance;
}
public function getAccountNumber(): string
{
// 只显示后4位
return '****' . substr($this->accountNumber, -4);
}
public function getTransactionHistory(int $limit = 10): array
{
return array_slice(array_reverse($this->transactions), 0, $limit);
}
public function freeze(): void
{
$this->frozen = true;
}
public function unfreeze(): void
{
$this->frozen = false;
}
private function logTransaction(string $type, float $amount): void
{
$this->transactions[] = [
'type' => $type,
'amount' => $amount,
'balance' => $this->balance,
'time' => date('Y-m-d H:i:s'),
];
}
}
$account = new BankAccount('6222021234567890', 1000);
$account->deposit(500);
$account->withdraw(200);
echo "余额: {$account->getBalance()}\n";
echo "账号: {$account->getAccountNumber()}\n";
print_r($account->getTransactionHistory());
?>
```
继承是代码复用的重要手段。子类可以继承父类的属性和方法,还能重写或扩展。
```php
class SavingsAccount extends BankAccount
{
private float $interestRate;
public function __construct(string $accountNumber, float $initialBalance = 0, float $interestRate = 0.03)
{
parent::__construct($accountNumber, $initialBalance);
$this->interestRate = $interestRate;
}
public function applyInterest(): void
{
$interest = $this->getBalance() * $this->interestRate;
if ($interest > 0) {
$this->deposit($interest);
echo "利息 {$interest} 已入账\n";
}
}
public function getInterestRate(): float
{
return $this->interestRate;
}
}
class CheckingAccount extends BankAccount
{
private float $overdraftLimit;
public function __construct(string $accountNumber, float $initialBalance = 0, float $overdraftLimit = 500)
{
parent::__construct($accountNumber, $initialBalance);
$this->overdraftLimit = $overdraftLimit;
}
public function withdraw(float $amount): bool
{
if ($amount > $this->getBalance() + $this->overdraftLimit) {
return false;
}
return parent::withdraw($amount);
}
}
$savings = new SavingsAccount('SAV001', 5000, 0.04);
$savings->deposit(1000);
$savings->applyInterest();
echo "储蓄账户余额: {$savings->getBalance()}\n";
$checking = new CheckingAccount('CHK001', 1000, 500);
$checking->withdraw(1200);
echo "支票账户余额: {$checking->getBalance()}\n";
?>
```
多态让不同类的对象可以通过相同的接口调用。PHP通过接口和抽象类实现多态。
```php
interface PaymentMethod
{
public function processPayment(float $amount): array;
public function refund(string $transactionId): array;
public function getName(): string;
}
class CreditCardPayment implements PaymentMethod
{
private string $cardNumber;
public function __construct(string $cardNumber)
{
$this->cardNumber = $cardNumber;
}
public function processPayment(float $amount): array
{
return [
'id' => 'CC-' . uniqid(),
'amount' => $amount,
'status' => 'approved',
'method' => '信用卡',
'last4' => substr($this->cardNumber, -4),
];
}
public function refund(string $transactionId): array
{
return ['id' => $transactionId, 'status' => 'refunded'];
}
public function getName(): string { return '信用卡支付'; }
}
class PayPalPayment implements PaymentMethod
{
private string $email;
public function __construct(string $email)
{
$this->email = $email;
}
public function processPayment(float $amount): array
{
return [
'id' => 'PP-' . uniqid(),
'amount' => $amount,
'status' => 'completed',
'method' => 'PayPal',
'email' => $this->email,
];
}
public function refund(string $transactionId): array
{
return ['id' => $transactionId, 'status' => 'completed'];
}
public function getName(): string { return 'PayPal支付'; }
}
class WeChatPayment implements PaymentMethod
{
public function processPayment(float $amount): array
{
return [
'id' => 'WX-' . uniqid(),
'amount' => $amount,
'status' => 'success',
'method' => '微信支付',
];
}
public function refund(string $transactionId): array
{
return ['id' => $transactionId, 'status' => 'success'];
}
public function getName(): string { return '微信支付'; }
}
class OrderProcessor
{
public function processOrder(float $amount, PaymentMethod $payment): void
{
echo "使用 {$payment->getName()} 处理 {$amount} 元的订单\n";
$result = $payment->processPayment($amount);
echo "支付结果: {$result['status']}\n";
}
}
$processor = new OrderProcessor();
$processor->processOrder(99.99, new CreditCardPayment('6222123456789012'));
$processor->processOrder(199.99, new PayPalPayment('user@example.com'));
$processor->processOrder(299.99, new WeChatPayment());
?>
```
PHP8引入了一些新的OOP特性,让代码写起来更方便了。构造器属性提升、联合类型、match表达式、命名参数等等。
```php
// PHP8特性
class Order
{
public function __construct(
public readonly string $id,
public readonly string $userId,
public readonly array $items,
public readonly float $total,
public string $status = 'pending',
public ?string $paidAt = null,
) {}
public function markAsPaid(): void
{
$this->status = 'paid';
$this->paidAt = date('Y-m-d H:i:s');
}
public function isPending(): bool
{
return $this->status === 'pending';
}
}
// match表达式
function getOrderStatusText(string $status): string
{
return match ($status) {
'pending' => '待支付',
'paid' => '已支付',
'shipped' => '已发货',
'delivered' => '已签收',
'cancelled' => '已取消',
default => '未知状态',
};
}
// 命名参数
$order = new Order(
id: 'ORD-' . uniqid(),
userId: 'USR-123',
items: [
['product' => 'PHP', 'quantity' => 1, 'price' => 99.99],
],
total: 99.99,
);
$order->markAsPaid();
echo "订单 {$order->id} 状态: " . getOrderStatusText($order->status) . "\n";
?>
```
面向对象不是银弹。有些场景用函数式或者面向过程写反而更清晰。好的代码不在于用了什么范式,而在于可读性和可维护性。但在大型项目中,面向对象的组织方式确实有利于代码的管理和扩展。
PHP面向对象编程深入理解
张小明
前端开发工程师
RISC-V架构入门:从模块化指令集到特权级设计的核心解析
1. RISC-V架构的设计哲学 我第一次接触RISC-V是在2014年,当时还在用ARM Cortex-M系列做嵌入式开发。偶然看到伯克利大学发布的这个开源指令集,第一反应是"这玩意儿真的能用吗?"十年后的今天,RISC-V已经席卷了整个嵌入式…
数据科学协作实战:跨机构大数据项目的工具链与协作框架设计
1. 项目概述:一场为期一年的数据科学“大协作”实验去年这个时候,我们几个来自不同机构、背景各异的数据科学家和工程师,决定干一件有点“理想主义”的事儿:发起一个名为“NSF大数据创新中心协作”的项目。这个标题听起来挺宏大&a…
微软女性计算研究员计划:系统性赋能与职业加速路径全解析
1. 项目概述:一次聚焦女性计算人才的系统性赋能在科技行业,尤其是计算机科学领域,性别失衡是一个长期存在且备受关注的议题。当看到“Microsoft fellowship program supports women in computing”这个标题时,我作为一名在科技圈摸…
保姆级教程:在Firefly RK3568开发板上搞定USB Host与OTG的完整配置流程
保姆级教程:在Firefly RK3568开发板上搞定USB Host与OTG的完整配置流程刚拿到Firefly RK3568开发板时,USB功能的配置往往是第一个需要攻克的难题。无论是连接键盘鼠标、外接存储设备,还是进行设备间的数据传输,USB Host和OTG模式都…
成都制造企业现金流排程总不准,AI智能体该先接哪些数据?
现金流排程不准,通常不是财务一个部门的问题很多制造企业到月底才发现资金紧,是因为现金流管理被简化成了银行余额、应收账款余额和付款申请表。这些数字都重要,但它们只能解释已经发生或即将发生的一小部分结果,不能回答老板和财…
微软NCWIT种子基金:如何通过“实践-社群-榜样”模型提升女性计算领域参与度
1. 项目概述:当学术种子基金遇上女性计算力量 最近看到一则消息,微软研究院和全美女性和信息技术中心(NCWIT)联合发起的“学术联盟种子基金”完成了第十一轮的资助。四所美国大学各拿到了1万美元,用于启动那些旨在吸引…