多态
什么是多态
多态(Polymorphism)是面向对象编程的四大特性之一。多态意味着"多种形态",在编程中指的是同一个接口或方法,作用于不同的对象时会产生不同的行为。简单来说,多态允许我们使用父类类型的变量来引用子类的对象,并调用子类重写的方法。
多态的核心概念
- 多种形态:同一操作作用于不同对象,产生不同的执行结果
- 动态绑定:在运行时确定调用哪个方法
- 统一接口:通过统一接口处理不同类型的对象
- 代码灵活性:编写更通用、可扩展的代码
多态的实现方式
1. 通过继承实现多态
<?php
// 基类
class Animal {
protected $name;
public function __construct($name) {
$this->name = $name;
}
// 定义通用的发声方法
public function makeSound() {
return "动物发出声音";
}
public function eat() {
return "{$this->name} 正在吃东西";
}
}
// 子类1:狗
class Dog extends Animal {
public function makeSound() {
return "{$this->name} 汪汪叫";
}
public function fetch() {
return "{$this->name} 正在捡球";
}
}
// 子类2:猫
class Cat extends Animal {
public function makeSound() {
return "{$this->name} 喵喵叫";
}
public function climb() {
return "{$this->name} 正在爬树";
}
}
// 子类3:鸟
class Bird extends Animal {
public function makeSound() {
return "{$this->name} 叽叽喳喳叫";
}
public function fly() {
return "{$this->name} 正在飞翔";
}
}
// 多态函数:可以处理任何Animal类型的对象
function makeAnimalSound(Animal $animal) {
echo $animal->makeSound() . "\n";
}
function letAnimalPerform(Animal $animal) {
echo $animal->makeSound() . "\n";
echo $animal->eat() . "\n";
// 使用instanceof检查具体类型,调用特定方法
if ($animal instanceof Dog) {
echo $animal->fetch() . "\n";
} elseif ($animal instanceof Cat) {
echo $animal->climb() . "\n";
} elseif ($animal instanceof Bird) {
echo $animal->fly() . "\n";
}
echo "---\n";
}
// 创建不同的动物对象
$animals = [
new Dog("旺财"),
new Cat("咪咪"),
new Bird("小黄")
];
// 演示多态
echo "=== 动物叫声 ===\n";
foreach ($animals as $animal) {
makeAnimalSound($animal);
}
echo "\n=== 动物表演 ===\n";
foreach ($animals as $animal) {
letAnimalPerform($animal);
}
?>
2. 通过接口实现多态
<?php
// 定义支付接口
interface PaymentInterface {
public function processPayment($amount);
public function getPaymentStatus();
public function refund($amount);
}
// 信用卡支付实现
class CreditCardPayment implements PaymentInterface {
private $cardNumber;
private $status = 'pending';
public function __construct($cardNumber) {
$this->cardNumber = $cardNumber;
}
public function processPayment($amount) {
echo "使用信用卡 {$this->cardNumber} 支付 ¥{$amount}\n";
$this->status = 'completed';
return true;
}
public function getPaymentStatus() {
return $this->status;
}
public function refund($amount) {
echo "退款 ¥{$amount} 到信用卡 {$this->cardNumber}\n";
$this->status = 'refunded';
return true;
}
}
// 支付宝支付实现
class AlipayPayment implements PaymentInterface {
private $accountId;
private $status = 'pending';
public function __construct($accountId) {
$this->accountId = $accountId;
}
public function processPayment($amount) {
echo "使用支付宝账号 {$this->accountId} 支付 ¥{$amount}\n";
$this->status = 'completed';
return true;
}
public function getPaymentStatus() {
return $this->status;
}
public function refund($amount) {
echo "退款 ¥{$amount} 到支付宝账号 {$this->accountId}\n";
$this->status = 'refunded';
return true;
}
}
// 微信支付实现
class WechatPayment implements PaymentInterface {
private $openId;
private $status = 'pending';
public function __construct($openId) {
$this->openId = $openId;
}
public function processPayment($amount) {
echo "使用微信 {$this->openId} 支付 ¥{$amount}\n";
$this->status = 'completed';
return true;
}
public function getPaymentStatus() {
return $this->status;
}
public function refund($amount) {
echo "退款 ¥{$amount} 到微信账号 {$this->openId}\n";
$this->status = 'refunded';
return true;
}
}
// 支付处理器类(使用多态)
class PaymentProcessor {
private $paymentMethods = [];
// 添加支付方式
public function addPaymentMethod(PaymentInterface $paymentMethod) {
$this->paymentMethods[] = $paymentMethod;
}
// 处理支付
public function processAllPayments($amount) {
foreach ($this->paymentMethods as $paymentMethod) {
if ($paymentMethod->processPayment($amount)) {
echo "支付成功!状态:" . $paymentMethod->getPaymentStatus() . "\n";
} else {
echo "支付失败!\n";
}
}
}
// 处理退款
public function processAllRefunds($amount) {
foreach ($this->paymentMethods as $paymentMethod) {
if ($paymentMethod->refund($amount)) {
echo "退款成功!状态:" . $paymentMethod->getPaymentStatus() . "\n";
}
}
}
}
// 使用示例
echo "=== 支付系统演示 ===\n\n";
$processor = new PaymentProcessor();
// 添加不同的支付方式
$processor->addPaymentMethod(new CreditCardPayment("1234-5678-9012-3456"));
$processor->addPaymentMethod(new AlipayPayment("user@example.com"));
$processor->addPaymentMethod(new WechatPayment("wx_openid_123456"));
// 处理支付
echo "--- 处理支付 ---\n";
$processor->processAllPayments(100);
echo "\n--- 处理退款 ---\n";
$processor->processAllRefunds(50);
?>
多态的实际应用:图形绘制系统
<?php
// 定义图形接口
interface ShapeInterface {
public function draw();
public function getArea();
public function getPerimeter();
public function resize($factor);
}
// 基础图形类
abstract class Shape implements ShapeInterface {
protected $color;
protected $x;
protected $y;
public function __construct($color = 'black', $x = 0, $y = 0) {
$this->color = $color;
$this->x = $x;
$this->y = $y;
}
public function move($newX, $newY) {
$this->x = $newX;
$this->y = $newY;
echo "图形移动到位置 ({$newX}, {$newY})\n";
}
abstract public function draw();
abstract public function getArea();
abstract public function getPerimeter();
abstract public function resize($factor);
}
// 圆形类
class Circle extends Shape {
private $radius;
public function __construct($radius, $color = 'red', $x = 0, $y = 0) {
parent::__construct($color, $x, $y);
$this->radius = $radius;
}
public function draw() {
echo "绘制一个半径为{$this->radius}的{$this->color}色圆形,位置({$this->x}, {$this->y})\n";
}
public function getArea() {
return pi() * $this->radius * $this->radius;
}
public function getPerimeter() {
return 2 * pi() * $this->radius;
}
public function resize($factor) {
$this->radius *= $factor;
echo "圆形缩放{$factor}倍,新半径:{$this->radius}\n";
}
}
// 矩形类
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($width, $height, $color = 'blue', $x = 0, $y = 0) {
parent::__construct($color, $x, $y);
$this->width = $width;
$this->height = $height;
}
public function draw() {
echo "绘制一个{$this->width}x{$this->height}的{$this->color}色矩形,位置({$this->x}, {$this->y})\n";
}
public function getArea() {
return $this->width * $this->height;
}
public function getPerimeter() {
return 2 * ($this->width + $this->height);
}
public function resize($factor) {
$this->width *= $factor;
$this->height *= $factor;
echo "矩形缩放{$factor}倍,新尺寸:{$this->width}x{$this->height}\n";
}
}
// 三角形类
class Triangle extends Shape {
private $side1;
private $side2;
private $side3;
public function __construct($side1, $side2, $side3, $color = 'green', $x = 0, $y = 0) {
parent::__construct($color, $x, $y);
$this->side1 = $side1;
$this->side2 = $side2;
$this->side3 = $side3;
}
public function draw() {
echo "绘制一个边长为{$this->side1}, {$this->side2}, {$this->side3}的{$this->color}色三角形,位置({$this->x}, {$this->y})\n";
}
public function getArea() {
// 使用海伦公式计算面积
$s = ($this->side1 + $this->side2 + $this->side3) / 2;
return sqrt($s * ($s - $this->side1) * ($s - $this->side2) * ($s - $this->side3));
}
public function getPerimeter() {
return $this->side1 + $this->side2 + $this->side3;
}
public function resize($factor) {
$this->side1 *= $factor;
$this->side2 *= $factor;
$this->side3 *= $factor;
echo "三角形缩放{$factor}倍,新边长:{$this->side1}, {$this->side2}, {$this->side3}\n";
}
}
// 图形绘制管理器
class DrawingManager {
private $shapes = [];
// 添加图形
public function addShape(ShapeInterface $shape) {
$this->shapes[] = $shape;
}
// 绘制所有图形
public function drawAll() {
echo "=== 绘制所有图形 ===\n";
foreach ($this->shapes as $shape) {
$shape->draw();
}
}
// 移动所有图形
public function moveAll($newX, $newY) {
echo "\n=== 移动所有图形 ===\n";
foreach ($this->shapes as $shape) {
$shape->move($newX, $newY);
}
}
// 缩放所有图形
public function resizeAll($factor) {
echo "\n=== 缩放所有图形 ===\n";
foreach ($this->shapes as $shape) {
$shape->resize($factor);
}
}
// 计算总面积
public function getTotalArea() {
$totalArea = 0;
foreach ($this->shapes as $shape) {
$totalArea += $shape->getArea();
}
return $totalArea;
}
// 显示所有图形信息
public function showShapeInfo() {
echo "\n=== 图形信息 ===\n";
foreach ($this->shapes as $index => $shape) {
echo "图形 " . ($index + 1) . ":\n";
echo " 面积: " . round($shape->getArea(), 2) . "\n";
echo " 周长: " . round($shape->getPerimeter(), 2) . "\n";
}
echo "总面积: " . round($this->getTotalArea(), 2) . "\n";
}
}
// 使用示例
$manager = new DrawingManager();
// 添加不同类型的图形
$manager->addShape(new Circle(5, 'red'));
$manager->addShape(new Rectangle(4, 6, 'blue'));
$manager->addShape(new Triangle(3, 4, 5, 'green'));
$manager->addShape(new Circle(3, 'yellow', 10, 20));
// 演示多态操作
$manager->drawAll();
$manager->moveAll(100, 100);
$manager->resizeAll(1.5);
$manager->showShapeInfo();
?>
多态的高级应用:插件系统
<?php
// 插件接口
interface PluginInterface {
public function getName();
public function getVersion();
public function getDescription();
public function execute($data);
public function isEnabled();
public function setEnabled($enabled);
}
// 基础插件类
abstract class BasePlugin implements PluginInterface {
protected $name;
protected $version;
protected $description;
protected $enabled = true;
public function __construct($name, $version, $description) {
$this->name = $name;
$this->version = $version;
$this->description = $description;
}
public function getName() {
return $this->name;
}
public function getVersion() {
return $this->version;
}
public function getDescription() {
return $this->description;
}
public function isEnabled() {
return $this->enabled;
}
public function setEnabled($enabled) {
$this->enabled = $enabled;
}
abstract public function execute($data);
}
// 日志插件
class LoggerPlugin extends BasePlugin {
private $logFile;
public function __construct() {
parent::__construct("日志插件", "1.0.0", "记录操作日志");
$this->logFile = 'application.log';
}
public function execute($data) {
if (!$this->isEnabled()) return;
$timestamp = date('Y-m-d H:i:s');
$logEntry = "[{$timestamp}] {$data}\n";
file_put_contents($this->logFile, $logEntry, FILE_APPEND);
echo "日志已记录:{$data}\n";
}
}
// 缓存插件
class CachePlugin extends BasePlugin {
private $cache = [];
public function __construct() {
parent::__construct("缓存插件", "2.1.0", "提供数据缓存功能");
}
public function execute($data) {
if (!$this->isEnabled()) return $data;
$key = md5(serialize($data));
if (isset($this->cache[$key])) {
echo "从缓存获取数据\n";
return $this->cache[$key];
}
$processedData = $this->processData($data);
$this->cache[$key] = $processedData;
echo "数据已缓存\n";
return $processedData;
}
private function processData($data) {
// 模拟数据处理
return "处理后的数据: " . $data;
}
public function clearCache() {
$this->cache = [];
echo "缓存已清空\n";
}
}
// 安全检查插件
class SecurityPlugin extends BasePlugin {
private $forbiddenWords = ['password', 'secret', 'token'];
public function __construct() {
parent::__construct("安全检查插件", "1.5.0", "检查敏感词汇");
}
public function execute($data) {
if (!$this->isEnabled()) return $data;
foreach ($this->forbiddenWords as $word) {
if (stripos($data, $word) !== false) {
echo "警告:检测到敏感词汇 '{$word}'\n";
return str_ireplace($word, '***', $data);
}
}
echo "安全检查通过\n";
return $data;
}
}
// 插件管理器
class PluginManager {
private $plugins = [];
// 注册插件
public function registerPlugin(PluginInterface $plugin) {
$this->plugins[] = $plugin;
echo "插件已注册:{$plugin->getName()} v{$plugin->getVersion()}\n";
}
// 执行所有插件
public function executePlugins($data) {
echo "\n=== 执行插件处理 ===\n";
$result = $data;
foreach ($this->plugins as $plugin) {
if ($plugin->isEnabled()) {
echo "执行插件:{$plugin->getName()}\n";
$result = $plugin->execute($result);
}
}
return $result;
}
// 列出所有插件
public function listPlugins() {
echo "\n=== 插件列表 ===\n";
foreach ($this->plugins as $plugin) {
$status = $plugin->isEnabled() ? '启用' : '禁用';
echo "名称: {$plugin->getName()}\n";
echo "版本: {$plugin->getVersion()}\n";
echo "描述: {$plugin->getDescription()}\n";
echo "状态: {$status}\n";
echo "---\n";
}
}
// 启用/禁用插件
public function togglePlugin($pluginName, $enabled) {
foreach ($this->plugins as $plugin) {
if ($plugin->getName() === $pluginName) {
$plugin->setEnabled($enabled);
$status = $enabled ? '启用' : '禁用';
echo "插件 {$pluginName} 已{$status}\n";
return true;
}
}
echo "未找到插件: {$pluginName}\n";
return false;
}
}
// 使用示例
echo "=== 插件系统演示 ===\n";
$pluginManager = new PluginManager();
// 注册插件
$pluginManager->registerPlugin(new LoggerPlugin());
$pluginManager->registerPlugin(new CachePlugin());
$pluginManager->registerPlugin(new SecurityPlugin());
// 列出插件
$pluginManager->listPlugins();
// 执行插件
$data = "用户输入的敏感数据包含password信息";
$result = $pluginManager->executePlugins($data);
echo "\n最终结果: {$result}\n";
// 禁用安全插件
$pluginManager->togglePlugin("安全检查插件", false);
$result2 = $pluginManager->executePlugins("这个数据没有敏感词");
echo "\n禁用安全插件后的结果: {$result2}\n";
?>
多态的优势
1. 代码复用和扩展性
<?php
// 不使用多态的硬编码方式
function processPayment_V1($type, $amount) {
if ($type === 'credit') {
// 信用卡处理逻辑
echo "处理信用卡支付\n";
} elseif ($type === 'alipay') {
// 支付宝处理逻辑
echo "处理支付宝支付\n";
} elseif ($type === 'wechat') {
// 微信支付处理逻辑
echo "处理微信支付\n";
}
// 添加新支付方式需要修改这个函数
}
// 使用多态的灵活方式
function processPayment_V2(PaymentInterface $payment, $amount) {
$payment->processPayment($amount);
// 添加新支付方式不需要修改这个函数
}
?>
2. 解耦和灵活性
多态减少了代码之间的耦合度,使系统更加灵活:
<?php
// 数据处理器接口
interface DataProcessorInterface {
public function process($data);
}
// 处理器管理器
class ProcessorManager {
private $processors = [];
public function addProcessor(DataProcessorInterface $processor) {
$this->processors[] = $processor;
}
public function processAll($data) {
foreach ($this->processors as $processor) {
$data = $processor->process($data);
}
return $data;
}
}
// 可以随时添加新的处理器,而不需要修改管理器
?>
多态与类型检查
instanceof操作符
<?php
function handleAnimal(Animal $animal) {
echo "处理动物: " . get_class($animal) . "\n";
// 使用instanceof检查具体类型
if ($animal instanceof Dog) {
$animal->fetch();
} elseif ($animal instanceof Cat) {
$animal->climb();
} else {
// 处理其他类型的动物
$animal->makeSound();
}
}
?>
类型提示和返回类型
<?php
class ShapeFactory {
public static function createShape(string $type): ShapeInterface {
switch ($type) {
case 'circle':
return new Circle(5);
case 'rectangle':
return new Rectangle(4, 6);
case 'triangle':
return new Triangle(3, 4, 5);
default:
throw new Exception("未知的图形类型: $type");
}
}
}
// 使用
$shape = ShapeFactory::createShape('circle');
$shape->draw();
?>
多态的最佳实践
1. 遵循里氏替换原则
子类应该能够替换父类,并且程序的行为不会改变:
<?php
// 好的设计:子类完全符合父类的契约
class Rectangle {
public function setWidth($width) { /* ... */ }
public function setHeight($height) { /* ... */ }
public function getArea() { /* ... */ }
}
class Square extends Rectangle {
// 正方形需要同时设置宽和高
public function setWidth($width) {
parent::setWidth($width);
parent::setHeight($width);
}
public function setHeight($height) {
parent::setWidth($height);
parent::setHeight($height);
}
}
// 这里Square不能完全替代Rectangle,因为行为不同
// 更好的做法是使用共同接口而不是继承
?>
2. 优先使用接口而不是具体类
<?php
// 好的做法:依赖接口
class ReportGenerator {
public function generate(DataExporterInterface $exporter) {
$data = $this->collectData();
return $exporter->export($data);
}
}
// 而不是依赖具体类
class ReportGenerator_Bad {
public function generate(PDFExporter $exporter) { // 限制了扩展性
$data = $this->collectData();
return $exporter->export($data);
}
}
?>
3. 避免过度使用instanceof
过多的类型检查可能表明设计有问题:
<?php
// 避免:过多的类型检查
function processShape(Shape $shape) {
if ($shape instanceof Circle) {
// 处理圆形
} elseif ($shape instanceof Rectangle) {
// 处理矩形
} elseif ($shape instanceof Triangle) {
// 处理三角形
}
}
// 更好:在子类中实现特定行为
abstract class Shape {
abstract public function process();
}
class Circle extends Shape {
public function process() {
// 圆形特有的处理逻辑
}
}
?>
通过本节的学习,你应该掌握了多态的概念、实现方式和应用场景。多态是面向对象编程的重要特性,它让代码更加灵活、可扩展和易于维护。在实际开发中,合理使用多态可以大大提高代码的质量和可维护性。