封装与继承

封装和继承是面向对象编程的两个核心概念。封装帮助我们保护数据和控制访问,而继承则让我们能够重用和扩展现有代码。这两个特性共同构建了面向对象编程的基础架构。

学习目标

完成本节学习后,你将能够:

  • 理解封装的概念和重要性
  • 掌握PHP的访问控制修饰符(public、protected、private)
  • 学会使用getter和setter方法
  • 理解继承的概念和优势
  • 掌握extends关键字的使用
  • 学会使用parent关键字访问父类成员
  • 理解方法重写和parent::语法
  • 了解继承中的构造函数调用

封装(Encapsulation)

什么是封装

封装是将数据(属性)和操作数据的方法(行为)捆绑在一起,并对外部隐藏对象的内部实现细节。封装提供了以下好处:

  1. 数据保护:防止外部代码直接修改对象内部状态
  2. 访问控制:通过公共接口控制对数据的访问
  3. 实现隐藏:隐藏内部实现细节,降低复杂性
  4. 维护性:可以修改内部实现而不影响外部代码

访问控制修饰符

PHP提供了三个访问控制修饰符:

1. public(公共的)

  • 可以在任何地方访问
  • 类内部、子类、类外部都可以访问

2. protected(受保护的)

  • 只能在类内部和子类中访问
  • 类外部无法直接访问

3. private(私有的)

  • 只能在定义它的类内部访问
  • 子类也无法访问

基本封装示例

<?php
class BankAccount {
    // 私有属性:只能通过类的方法访问
    private $accountNumber;
    private $balance;
    private $ownerName;
    private $isLocked = false;

    // 受保护的属性:子类可以访问
    protected $accountType;
    protected $createdDate;

    // 公有属性:任何地方都可以访问(通常不推荐)
    public $bankName = "示例银行";

    // 构造函数
    public function __construct($accountNumber, $ownerName, $initialBalance = 0) {
        $this->accountNumber = $this->validateAccountNumber($accountNumber);
        $this->ownerName = $ownerName;
        $this->balance = $this->validateBalance($initialBalance);
        $this->accountType = "储蓄账户";
        $this->createdDate = date('Y-m-d H:i:s');

        echo "创建账户:{$this->accountNumber},持有人:{$this->ownerName}\n";
    }

    // 公有方法:外部接口
    public function deposit($amount) {
        if ($this->isLocked) {
            throw new Exception("账户已锁定,无法存款");
        }

        $amount = $this->validateAmount($amount);
        $this->balance += $amount;

        echo "存入:¥{$amount},余额:¥{$this->balance}\n";
        return $this->balance;
    }

    public function withdraw($amount) {
        if ($this->isLocked) {
            throw new Exception("账户已锁定,无法取款");
        }

        $amount = $this->validateAmount($amount);

        if ($this->balance < $amount) {
            throw new Exception("余额不足");
        }

        $this->balance -= $amount;
        echo "取出:¥{$amount},余额:¥{$this->balance}\n";
        return $this->balance;
    }

    public function getBalance() {
        return $this->balance;
    }

    public function getAccountNumber() {
        return $this->maskAccountNumber($this->accountNumber);
    }

    public function getOwnerName() {
        return $this->ownerName;
    }

    public function lock() {
        $this->isLocked = true;
        echo "账户 {$this->accountNumber} 已锁定\n";
    }

    public function unlock() {
        $this->isLocked = false;
        echo "账户 {$this->accountNumber} 已解锁\n";
    }

    // 受保护的方法:子类可以访问
    protected function validateAmount($amount) {
        if (!is_numeric($amount) || $amount <= 0) {
            throw new Exception("金额必须是正数");
        }
        return (float)$amount;
    }

    protected function validateAccountNumber($accountNumber) {
        if (empty($accountNumber) || strlen($accountNumber) < 10) {
            throw new Exception("账户号码格式不正确");
        }
        return $accountNumber;
    }

    protected function validateBalance($balance) {
        if (!is_numeric($balance) || $balance < 0) {
            throw new Exception("初始余额必须是非负数");
        }
        return (float)$balance;
    }

    protected function maskAccountNumber($accountNumber) {
        return substr($accountNumber, 0, 4) . '****' . substr($accountNumber, -4);
    }

    // 私有方法:只有类内部可以访问
    private function logTransaction($type, $amount) {
        $timestamp = date('Y-m-d H:i:s');
        echo "[$timestamp] {$type}: ¥{$amount}\n";
    }

    public function getAccountInfo() {
        return [
            'account_number' => $this->getAccountNumber(),
            'owner' => $this->ownerName,
            'balance' => $this->balance,
            'type' => $this->accountType,
            'created_date' => $this->createdDate,
            'is_locked' => $this->isLocked
        ];
    }
}

// 使用银行账户类
echo "=== 基本封装示例 ===\n";

try {
    $account = new BankAccount("1234567890", "张三", 1000.00);

    // 通过公有方法访问
    echo "账户信息:\n";
    echo "账号:{$account->getAccountNumber()}\n";
    echo "户主:{$account->getOwnerName()}\n";
    echo "余额:¥{$account->getBalance()}\n";

    // 进行操作
    $account->deposit(500.00);
    $account->withdraw(200.00);

    // 访问公共属性
    echo "银行:{$account->bankName}\n";

    // 这些操作会导致错误:
    // echo $account->accountNumber;  // 错误:无法访问私有属性
    // echo $account->balance;        // 错误:无法访问私有属性
    // $account->balance = 10000;     // 错误:无法修改私有属性

} catch (Exception $e) {
    echo "错误:" . $e->getMessage() . "\n";
}
?>

Getter和Setter方法

Getter和Setter方法提供了一种受控的方式来访问和修改私有属性。

<?php
class Product {
    private $id;
    private $name;
    private $price;
    private $description;
    private $inStock;
    private $minStockLevel = 10;

    public function __construct($id, $name, $price) {
        $this->id = $this->validateId($id);
        $this->name = $this->validateName($name);
        $this->price = $this->validatePrice($price);
        $this->inStock = true;
    }

    // Getter方法
    public function getId() {
        return $this->id;
    }

    public function getName() {
        return $this->name;
    }

    public function getPrice() {
        return $this->price;
    }

    public function getDescription() {
        return $this->description ?: '暂无描述';
    }

    public function isInStock() {
        return $this->inStock;
    }

    public function getMinStockLevel() {
        return $this->minStockLevel;
    }

    // Setter方法(带验证)
    public function setName($name) {
        $this->name = $this->validateName($name);
        echo "产品名称已更新为:{$this->name}\n";
    }

    public function setPrice($price) {
        $this->price = $this->validatePrice($price);
        echo "产品价格已更新为:¥{$this->price}\n";
    }

    public function setDescription($description) {
        $this->description = $this->validateDescription($description);
        echo "产品描述已更新\n";
    }

    public function setInStock($inStock) {
        $this->inStock = (bool)$inStock;
        echo "产品库存状态:" . ($this->inStock ? "有货" : "缺货") . "\n";
    }

    public function setMinStockLevel($level) {
        $this->minStockLevel = $this->validateStockLevel($level);
        echo "最小库存警戒线设置为:{$this->minStockLevel}\n";
    }

    // 带业务逻辑的设置方法
    public function applyDiscount($percentage) {
        if ($percentage <= 0 || $percentage > 100) {
            throw new Exception("折扣百分比必须在0-100之间");
        }

        $discount = $this->price * ($percentage / 100);
        $this->price -= $discount;

        echo "应用 {$percentage}% 折扣,折扣金额:¥{$discount}\n";
        echo "折后价格:¥{$this->price}\n";

        return $this->price;
    }

    public function increasePrice($amount) {
        if ($amount <= 0) {
            throw new Exception("增加金额必须为正数");
        }

        $this->price += $amount;
        echo "价格增加:¥{$amount},新价格:¥{$this->price}\n";

        return $this->price;
    }

    // 验证方法
    private function validateId($id) {
        if (empty($id)) {
            throw new Exception("产品ID不能为空");
        }
        return $id;
    }

    private function validateName($name) {
        if (empty($name)) {
            throw new Exception("产品名称不能为空");
        }
        if (strlen($name) > 100) {
            throw new Exception("产品名称过长");
        }
        return trim($name);
    }

    private function validatePrice($price) {
        if (!is_numeric($price) || $price < 0) {
            throw new Exception("价格必须是非负数");
        }
        return (float)$price;
    }

    private function validateDescription($description) {
        if (strlen($description) > 500) {
            throw new Exception("描述过长,最多500字符");
        }
        return $description;
    }

    private function validateStockLevel($level) {
        if (!is_numeric($level) || $level < 0) {
            throw new Exception("库存警戒线必须是非负数");
        }
        return (int)$level;
    }

    // 只读属性(只有getter)
    public function getFormattedPrice() {
        return '¥' . number_format($this->price, 2);
    }

    public function getProductInfo() {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'price' => $this->getFormattedPrice(),
            'description' => $this->getDescription(),
            'in_stock' => $this->isInStock(),
            'min_stock_level' => $this->minStockLevel
        ];
    }
}

// 使用Getter和Setter
echo "=== Getter和Setter方法示例 ===\n";

try {
    $product = new Product("P001", "智能手机", 2999.00);

    echo "\n初始产品信息:\n";
    print_r($product->getProductInfo());

    echo "\n修改产品属性:\n";
    $product->setName("智能手机 Pro");
    $product->setPrice(3299.00);
    $product->setDescription("新款智能手机,配置更强大");

    echo "\n应用折扣:\n";
    $product->applyDiscount(10);

    echo "\n最终产品信息:\n";
    print_r($product->getProductInfo());

} catch (Exception $e) {
    echo "错误:" . $e->getMessage() . "\n";
}
?>

高级封装技巧

<?php
class Configuration {
    private $settings = [];
    private $readOnly = [];
    private $validatorCallbacks = [];

    public function __construct() {
        // 初始化默认配置
        $this->initializeDefaults();
    }

    // 设置配置值
    public function set($key, $value) {
        if ($this->isReadOnly($key)) {
            throw new Exception("配置项 '$key' 为只读");
        }

        $oldValue = $this->get($key);

        // 执行验证回调
        if (isset($this->validatorCallbacks[$key])) {
            $callback = $this->validatorCallbacks[$key];
            if (!$callback($value)) {
                throw new Exception("配置项 '$key' 的值无效");
            }
        }

        $this->settings[$key] = $value;

        if ($oldValue !== $value) {
            $this->onConfigChange($key, $oldValue, $value);
        }

        return $this;
    }

    // 获取配置值
    public function get($key, $default = null) {
        return $this->settings[$key] ?? $default;
    }

    // 批量设置
    public function setMultiple(array $settings) {
        foreach ($settings as $key => $value) {
            $this->set($key, $value);
        }
        return $this;
    }

    // 检查配置是否存在
    public function has($key) {
        return array_key_exists($key, $this->settings);
    }

    // 删除配置项
    public function remove($key) {
        if ($this->isReadOnly($key)) {
            throw new Exception("无法删除只读配置项 '$key'");
        }

        unset($this->settings[$key]);
        return $this;
    }

    // 设置只读配置
    public function setReadOnly($key) {
        $this->readOnly[$key] = true;
        return $this;
    }

    // 设置验证器
    public function setValidator($key, callable $validator) {
        $this->validatorCallbacks[$key] = $validator;
        return $this;
    }

    // 获取所有配置
    public function all() {
        return $this->settings;
    }

    // 清空所有非只读配置
    public function clear() {
        $readOnlySettings = array_intersect_key($this->settings, $this->readOnly);
        $this->settings = $readOnlySettings;
        return $this;
    }

    // 从数组加载配置
    public function loadFromArray(array $config) {
        $this->settings = array_merge($this->settings, $config);
        return $this;
    }

    // 保存到数组
    public function toArray() {
        return $this->settings;
    }

    // 魔术方法:支持数组式访问
    public function __get($key) {
        return $this->get($key);
    }

    public function __set($key, $value) {
        $this->set($key, $value);
    }

    public function __isset($key) {
        return $this->has($key);
    }

    public function __unset($key) {
        $this->remove($key);
    }

    // 私有方法
    private function isReadOnly($key) {
        return isset($this->readOnly[$key]);
    }

    private function initializeDefaults() {
        $this->settings = [
            'app_name' => 'MyApp',
            'version' => '1.0.0',
            'debug' => false,
            'timezone' => 'Asia/Shanghai',
            'max_connections' => 100,
            'timeout' => 30
        ];

        // 设置只读配置
        $this->setReadOnly('version');

        // 设置验证器
        $this->setValidator('debug', function($value) {
            return is_bool($value);
        });

        $this->setValidator('max_connections', function($value) {
            return is_int($value) && $value > 0 && $value <= 1000;
        });
    }

    private function onConfigChange($key, $oldValue, $newValue) {
        echo "配置变更:$key 从 '$oldValue' 改为 '$newValue'\n";
    }
}

// 使用高级封装的配置类
echo "=== 高级封装技巧示例 ===\n";

try {
    $config = new Configuration();

    echo "\n初始配置:\n";
    print_r($config->all());

    echo "\n修改配置:\n";
    $config->set('debug', true);
    $config->set('max_connections', 50);

    echo "\n尝试设置只读配置(会失败):\n";
    try {
        $config->set('version', '2.0.0');
    } catch (Exception $e) {
        echo "预期错误:" . $e->getMessage() . "\n";
    }

    echo "\n尝试设置无效值(会失败):\n";
    try {
        $config->set('max_connections', -1);
    } catch (Exception $e) {
        echo "预期错误:" . $e->getMessage() . "\n";
    }

    echo "\n使用魔术方法访问配置:\n";
    echo "应用名称:{$config->app_name}\n";
    echo "调试模式:" . ($config->debug ? '开启' : '关闭') . "\n";

    // 数组式访问
    if (isset($config->debug)) {
        echo "调试模式已设置\n";
    }

} catch (Exception $e) {
    echo "错误:" . $e->getMessage() . "\n";
}
?>

继承(Inheritance)

什么是继承

继承允许一个类(子类)获得另一个类(父类)的属性和方法。继承提供了以下好处:

  1. 代码重用:子类可以重用父类的代码
  2. 扩展功能:在父类基础上添加新功能
  3. 层次结构:创建清晰的类层次关系
  4. 多态支持:为多态提供基础

基本继承语法

<?php
class ParentClass {
    // 父类的属性和方法
}

class ChildClass extends ParentClass {
    // 子类的新属性和方法
}
?>

基本继承示例

<?php
// 父类:动物
class Animal {
    protected $name;
    protected $age;
    protected $species;

    public function __construct($name, $age, $species) {
        $this->name = $name;
        $this->age = $age;
        $this->species = $species;
        echo "创建了一个 {$this->species}:{$this->name}\n";
    }

    public function eat() {
        echo "{$this->name} 正在吃东西\n";
    }

    public function sleep() {
        echo "{$this->name} 正在睡觉\n";
    }

    public function makeSound() {
        echo "{$this->name} 发出了声音\n";
    }

    public function getAge() {
        return $this->age;
    }

    public function getName() {
        return $this->name;
    }

    public function getSpecies() {
        return $this->species;
    }

    public function celebrateBirthday() {
        $this->age++;
        echo "{$this->name} 过生日了,现在 {$this->age} 岁!\n";
    }

    public function getInfo() {
        return "这是一只 {$this->age} 岁的 {$this->species},名字叫 {$this->name}";
    }
}

// 子类:狗
class Dog extends Animal {
    private $breed;

    public function __construct($name, $age, $breed) {
        // 调用父类构造函数
        parent::__construct($name, $age, "狗");
        $this->breed = $breed;
        echo "这是一只 {$this->breed}\n";
    }

    // 新增方法
    public function wagTail() {
        echo "{$this->name} 摇着尾巴\n";
    }

    public function fetch($item) {
        echo "{$this->name} 去取 {$item}\n";
    }

    // 重写父类方法
    public function makeSound() {
        echo "{$this->name} 汪汪叫\n";
    }

    // 扩展父类方法
    public function getInfo() {
        $parentInfo = parent::getInfo();
        return $parentInfo . ",品种是 {$this->breed}";
    }

    public function getBreed() {
        return $this->breed;
    }
}

// 子类:猫
class Cat extends Animal {
    private $color;
    private $isIndoor;

    public function __construct($name, $age, $color, $isIndoor = true) {
        parent::__construct($name, $age, "猫");
        $this->color = $color;
        $this->isIndoor = $isIndoor;
        echo "这是一只 {$this->color} 的" . ($this->isIndoor ? "室内" : "室外") . "猫\n";
    }

    // 新增方法
    public function purr() {
        echo "{$this->name} 发出呼噜声\n";
    }

    public function scratch() {
        echo "{$this->name} 磨爪子\n";
    }

    public function climb() {
        echo "{$this->name} 爬到了高处\n";
    }

    // 重写父类方法
    public function makeSound() {
        echo "{$this->name} 喵喵叫\n";
        $this->purr();
    }

    // 扩展父类方法
    public function getInfo() {
        $parentInfo = parent::getInfo();
        return $parentInfo . ",颜色是 {$this->color}," .
               ($this->isIndoor ? "室内" : "室外") . "猫";
    }

    public function getColor() {
        return $this->color;
    }

    public function isIndoor() {
        return $this->isIndoor;
    }
}

// 使用继承
echo "=== 基本继承示例 ===\n";

echo "\n创建动物对象:\n";
$dog = new Dog("旺财", 3, "金毛");
$cat = new Cat("咪咪", 2, "橘色");

echo "\n测试狗的行为:\n";
$dog->eat();
$dog->makeSound();
$dog->wagTail();
$dog->fetch("球");

echo "\n测试猫的行为:\n";
$cat->eat();
$cat->makeSound();
$cat->climb();
$cat->scratch();

echo "\n动物信息:\n";
echo $dog->getInfo() . "\n";
echo $cat->getInfo() . "\n";

echo "\n生日庆祝:\n";
$dog->celebrateBirthday();
$cat->celebrateBirthday();
?>

复杂的继承示例

<?php
// 父类:车辆
class Vehicle {
    protected $brand;
    protected $model;
    protected $year;
    protected $speed = 0;
    protected $maxSpeed;
    protected $fuel = 100;
    protected $isRunning = false;

    public function __construct($brand, $model, $year, $maxSpeed) {
        $this->brand = $brand;
        $this->model = $model;
        $this->year = $year;
        $this->maxSpeed = $maxSpeed;

        echo "创建了 {$this->brand} {$this->model} ({$this->year}年)\n";
    }

    public function start() {
        if ($this->fuel <= 0) {
            echo "燃料不足,无法启动\n";
            return false;
        }

        if (!$this->isRunning) {
            $this->isRunning = true;
            echo "{$this->brand} {$this->model} 启动了\n";
            return true;
        } else {
            echo "车辆已经在运行中\n";
            return true;
        }
    }

    public function stop() {
        if ($this->isRunning) {
            $this->speed = 0;
            $this->isRunning = false;
            echo "{$this->brand} {$this->model} 停止了\n";
        } else {
            echo "车辆已经停止\n";
        }
        return true;
    }

    public function accelerate($amount) {
        if (!$this->isRunning) {
            echo "请先启动车辆\n";
            return false;
        }

        $newSpeed = $this->speed + $amount;
        if ($newSpeed > $this->maxSpeed) {
            echo "不能超过最高速度 {$this->maxSpeed} km/h\n";
            return false;
        }

        $this->speed = $newSpeed;
        $this->consumeFuel($amount * 0.1);
        echo "加速到 {$this->speed} km/h\n";
        return true;
    }

    public function brake($amount) {
        if ($this->speed >= $amount) {
            $this->speed -= $amount;
        } else {
            $this->speed = 0;
        }
        echo "减速到 {$this->speed} km/h\n";
        return $this->speed;
    }

    public function refuel($amount) {
        $this->fuel = min(100, $this->fuel + $amount);
        echo "加油 {$amount}%,当前燃料:{$this->fuel}%\n";
    }

    public function getFuel() {
        return $this->fuel;
    }

    public function getSpeed() {
        return $this->speed;
    }

    public function isRunning() {
        return $this->isRunning;
    }

    public function getMaxSpeed() {
        return $this->maxSpeed;
    }

    public function getVehicleInfo() {
        return [
            'brand' => $this->brand,
            'model' => $this->model,
            'year' => $this->year,
            'speed' => $this->speed,
            'max_speed' => $this->maxSpeed,
            'fuel' => $this->fuel,
            'is_running' => $this->isRunning
        ];
    }

    protected function consumeFuel($amount) {
        $this->fuel = max(0, $this->fuel - $amount);
        if ($this->fuel <= 10) {
            echo "警告:燃料不足!\n";
        }
        if ($this->fuel <= 0) {
            $this->stop();
            echo "燃料耗尽,车辆停止\n";
        }
    }
}

// 子类:汽车
class Car extends Vehicle {
    private $doors;
    private $trunkSize;
    private $isConvertible;

    public function __construct($brand, $model, $year, $maxSpeed, $doors, $trunkSize, $isConvertible = false) {
        parent::__construct($brand, $model, $year, $maxSpeed);
        $this->doors = $doors;
        $this->trunkSize = $trunkSize;
        $this->isConvertible = $isConvertible;
    }

    public function openTrunk() {
        echo "打开了后备箱(容量:{$this->trunkSize}L)\n";
    }

    public function closeTrunk() {
        echo "关闭了后备箱\n";
    }

    public function honk() {
        echo "嘀嘀!\n";
    }

    public function turnOnAirConditioner() {
        echo "打开空调\n";
    }

    public function playRadio($station) {
        echo "收音机调到 {$station} 频道\n";
    }

    public function openRoof() {
        if ($this->isConvertible) {
            echo "打开了敞篷\n";
        } else {
            echo "这辆车不是敞篷车\n";
        }
    }

    public function closeRoof() {
        if ($this->isConvertible) {
            echo "关闭了敞篷\n";
        }
    }

    public function getDoors() {
        return $this->doors;
    }

    public function getTrunkSize() {
        return $this->trunkSize;
    }

    public function isConvertible() {
        return $this->isConvertible;
    }

    public function getVehicleInfo() {
        $info = parent::getVehicleInfo();
        $info['doors'] = $this->doors;
        $info['trunk_size'] = $this->trunkSize;
        $info['is_convertible'] = $this->isConvertible;
        return $info;
    }
}

// 子类:摩托车
class Motorcycle extends Vehicle {
    private $engineCC;
    private $hasWindshield;
    private $type; // 跑车、巡航车等

    public function __construct($brand, $model, $year, $maxSpeed, $engineCC, $hasWindshield = false, $type = "普通") {
        parent::__construct($brand, $model, $year, $maxSpeed);
        $this->engineCC = $engineCC;
        $this->hasWindshield = $hasWindshield;
        $this->type = $type;
    }

    public function wheelie() {
        if ($this->speed >= 20 && $this->speed <= 60) {
            echo "翘起前轮!\n";
        } else {
            echo "速度不适合做翘头动作\n";
        }
    }

    public function lean($direction) {
        if ($this->speed >= 30) {
            echo "向{$direction}倾斜转弯\n";
        } else {
            echo "速度太慢,无法倾斜\n";
        }
    }

    public function installWindshield() {
        if (!$this->hasWindshield) {
            $this->hasWindshield = true;
            echo "安装了挡风玻璃\n";
        } else {
            echo "已经有挡风玻璃了\n";
        }
    }

    public function removeWindshield() {
        if ($this->hasWindshield) {
            $this->hasWindshield = false;
            echo "拆卸了挡风玻璃\n";
        } else {
            echo "没有挡风玻璃可拆卸\n";
        }
    }

    // 重写父类方法:摩托车燃料消耗不同
    protected function consumeFuel($amount) {
        parent::consumeFuel($amount * 0.7); // 摩托车更省油
    }

    public function getEngineCC() {
        return $this->engineCC;
    }

    public function hasWindshield() {
        return $this->hasWindshield;
    }

    public function getType() {
        return $this->type;
    }

    public function getVehicleInfo() {
        $info = parent::getVehicleInfo();
        $info['engine_cc'] = $this->engineCC;
        $info['has_windshield'] = $this->hasWindshield;
        $info['type'] = $this->type;
        return $info;
    }
}

// 使用复杂继承
echo "=== 复杂继承示例 ===\n";

echo "\n创建车辆:\n";
$car = new Car("特斯拉", "Model 3", 2023, 225, 4, 425, false);
$motorcycle = new Motorcycle("本田", "CBR600RR", 2022, 260, 600, true, "跑车");

echo "\n测试汽车:\n";
$car->start();
$car->accelerate(50);
$car->honk();
$car->turnOnAirConditioner();
$car->openTrunk();
$car->getVehicleInfo();

echo "\n测试摩托车:\n";
$motorcycle->start();
$motorcycle->accelerate(40);
$motorcycle->wheelie();
$motorcycle->lean("左");
$motorcycle->accelerate(80);
$motorcycle->wheelie();

echo "\n车辆信息对比:\n";
echo "汽车:\n";
print_r($car->getVehicleInfo());
echo "\n摩托车:\n";
print_r($motorcycle->getVehicleInfo());
?>

继承中的构造函数

<?php
// 父类:用户
class User {
    protected $id;
    protected $username;
    protected $email;
    protected $passwordHash;
    protected $createdAt;
    protected $lastLogin;
    protected $isActive = true;

    public function __construct($username, $email, $password) {
        $this->id = uniqid('user_');
        $this->username = $this->validateUsername($username);
        $this->email = $this->validateEmail($email);
        $this->passwordHash = $this->hashPassword($password);
        $this->createdAt = date('Y-m-d H:i:s');

        echo "创建用户:{$this->username}\n";
    }

    protected function validateUsername($username) {
        if (empty($username) || strlen($username) < 3) {
            throw new Exception("用户名至少需要3个字符");
        }
        return $username;
    }

    protected function validateEmail($email) {
        if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
            throw new Exception("邮箱格式不正确");
        }
        return $email;
    }

    protected function hashPassword($password) {
        if (strlen($password) < 6) {
            throw new Exception("密码至少需要6个字符");
        }
        return password_hash($password, PASSWORD_DEFAULT);
    }

    public function login($password) {
        if (!$this->isActive) {
            throw new Exception("账户已被禁用");
        }

        if (password_verify($password, $this->passwordHash)) {
            $this->lastLogin = date('Y-m-d H:i:s');
            echo "用户 {$this->username} 登录成功\n";
            return true;
        } else {
            throw new Exception("密码错误");
        }
    }

    public function logout() {
        echo "用户 {$this->username} 已登出\n";
    }

    public function activate() {
        $this->isActive = true;
        echo "账户 {$this->username} 已激活\n";
    }

    public function deactivate() {
        $this->isActive = false;
        echo "账户 {$this->username} 已禁用\n";
    }

    // Getter方法
    public function getId() { return $this->id; }
    public function getUsername() { return $this->username; }
    public function getEmail() { return $this->email; }
    public function getCreatedAt() { return $this->createdAt; }
    public function getLastLogin() { return $this->lastLogin; }
    public function isActive() { return $this->isActive; }

    public function getUserInfo() {
        return [
            'id' => $this->id,
            'username' => $this->username,
            'email' => $this->email,
            'created_at' => $this->createdAt,
            'last_login' => $this->lastLogin,
            'is_active' => $this->isActive
        ];
    }
}

// 子类:管理员
class Admin extends User {
    private $adminLevel;
    private $permissions;
    private $department;

    public function __construct($username, $email, $password, $adminLevel = 1, $department = '系统') {
        // 先调用父类构造函数
        parent::__construct($username, $email, $password);

        // 然后初始化子类特有属性
        $this->adminLevel = $this->validateAdminLevel($adminLevel);
        $this->department = $department;
        $this->permissions = $this->getDefaultPermissions();

        echo "管理员 {$this->username} (级别:{$this->adminLevel}) 已创建\n";
    }

    private function validateAdminLevel($level) {
        if (!is_int($level) || $level < 1 || $level > 5) {
            throw new Exception("管理员级别必须在1-5之间");
        }
        return $level;
    }

    private function getDefaultPermissions() {
        $permissions = ['user_management'];

        if ($this->adminLevel >= 2) {
            $permissions[] = 'content_management';
        }
        if ($this->adminLevel >= 3) {
            $permissions[] = 'system_config';
        }
        if ($this->adminLevel >= 4) {
            $permissions[] = 'data_export';
        }
        if ($this->adminLevel >= 5) {
            $permissions[] = 'system_admin';
        }

        return $permissions;
    }

    public function hasPermission($permission) {
        return in_array($permission, $this->permissions);
    }

    public function addPermission($permission) {
        if (!$this->hasPermission($permission)) {
            $this->permissions[] = $permission;
            echo "管理员 {$this->username} 获得权限:{$permission}\n";
        }
        return $this;
    }

    public function removePermission($permission) {
        if ($this->hasPermission($permission) && $permission !== 'user_management') {
            $key = array_search($permission, $this->permissions);
            unset($this->permissions[$key]);
            $this->permissions = array_values($this->permissions);
            echo "管理员 {$this->username} 失去权限:{$permission}\n";
        }
        return $this;
    }

    public function manageUsers() {
        if ($this->hasPermission('user_management')) {
            echo "管理员 {$this->username} 正在管理用户\n";
        } else {
            throw new Exception("没有用户管理权限");
        }
    }

    public function configureSystem() {
        if ($this->hasPermission('system_config')) {
            echo "管理员 {$this->username} 正在配置系统\n";
        } else {
            throw new Exception("没有系统配置权限");
        }
    }

    public function exportData() {
        if ($this->hasPermission('data_export')) {
            echo "管理员 {$this->username} 正在导出数据\n";
        } else {
            throw new Exception("没有数据导出权限");
        }
    }

    // 重写父类方法
    public function getUserInfo() {
        $info = parent::getUserInfo();
        $info['admin_level'] = $this->adminLevel;
        $info['department'] = $this->department;
        $info['permissions'] = $this->permissions;
        return $info;
    }

    // Getter方法
    public function getAdminLevel() { return $this->adminLevel; }
    public function getDepartment() { return $this->department; }
    public function getPermissions() { return $this->permissions; }
}

// 子类:VIP用户
class VIPUser extends User {
    private $vipLevel;
    private $expirationDate;
    private $specialFeatures;

    public function __construct($username, $email, $password, $vipLevel = 1, $duration = '1 year') {
        parent::__construct($username, $email, $password);

        $this->vipLevel = $this->validateVipLevel($vipLevel);
        $this->expirationDate = $this->calculateExpirationDate($duration);
        $this->specialFeatures = $this->getVipFeatures();

        echo "VIP用户 {$this->username} (级别:{$this->vipLevel}) 已创建\n";
        echo "有效期至:{$this->expirationDate}\n";
    }

    private function validateVipLevel($level) {
        if (!is_int($level) || $level < 1 || $level > 3) {
            throw new Exception("VIP级别必须在1-3之间");
        }
        return $level;
    }

    private function calculateExpirationDate($duration) {
        $date = new DateTime();
        if ($duration === '6 months') {
            $date->add(new DateInterval('P6M'));
        } elseif ($duration === '1 year') {
            $date->add(new DateInterval('P1Y'));
        } elseif ($duration === '2 years') {
            $date->add(new DateInterval('P2Y'));
        }
        return $date->format('Y-m-d');
    }

    private function getVipFeatures() {
        $features = ['priority_support'];

        if ($this->vipLevel >= 2) {
            $features[] = 'exclusive_content';
            $features[] = 'no_ads';
        }
        if ($this->vipLevel >= 3) {
            $features[] = 'unlimited_downloads';
            $features[] = 'personal_manager';
        }

        return $features;
    }

    public function isVipActive() {
        return $this->expirationDate >= date('Y-m-d');
    }

    public function extendVip($duration) {
        $currentDate = new DateTime($this->expirationDate);
        if ($duration === '6 months') {
            $currentDate->add(new DateInterval('P6M'));
        } elseif ($duration === '1 year') {
            $currentDate->add(new DateInterval('P1Y'));
        }
        $this->expirationDate = $currentDate->format('Y-m-d');
        echo "VIP已延期至 {$this->expirationDate}\n";
    }

    public function hasFeature($feature) {
        return in_array($feature, $this->specialFeatures) && $this->isVipActive();
    }

    public function accessExclusiveContent() {
        if ($this->hasFeature('exclusive_content')) {
            echo "VIP用户 {$this->username} 正在访问独占内容\n";
        } else {
            throw new Exception("没有访问独占内容的权限");
        }
    }

    public function downloadFile($filename) {
        if ($this->hasFeature('unlimited_downloads')) {
            echo "VIP用户 {$this->username} 正在下载 {$filename}\n";
        } else {
            echo "下载次数受限,请升级VIP\n";
        }
    }

    // 重写父类方法
    public function getUserInfo() {
        $info = parent::getUserInfo();
        $info['vip_level'] = $this->vipLevel;
        $info['expiration_date'] = $this->expirationDate;
        $info['special_features'] = $this->specialFeatures;
        $info['is_vip_active'] = $this->isVipActive();
        return $info;
    }

    // Getter方法
    public function getVipLevel() { return $this->vipLevel; }
    public function getExpirationDate() { return $this->expirationDate; }
    public function getSpecialFeatures() { return $this->specialFeatures; }
}

// 使用继承中的构造函数
echo "=== 继承中的构造函数示例 ===\n";

try {
    echo "\n创建不同类型的用户:\n";
    $user = new User("普通用户", "user@example.com", "password123");
    $admin = new Admin("系统管理员", "admin@example.com", "adminpass", 3, "技术部");
    $vip = new VIPUser("VIP会员", "vip@example.com", "vippass", 2, "1 year");

    echo "\n用户登录测试:\n";
    $user->login("password123");
    $admin->login("adminpass");
    $vip->login("vippass");

    echo "\n管理员权限测试:\n";
    $admin->manageUsers();
    $admin->configureSystem();
    try {
        $admin->exportData(); // 可能失败,取决于管理员级别
    } catch (Exception $e) {
        echo $e->getMessage() . "\n";
    }

    echo "\nVIP功能测试:\n";
    $vip->accessExclusiveContent();
    $vip->downloadFile("movie.mp4");

    echo "\n用户信息对比:\n";
    echo "普通用户:\n";
    print_r($user->getUserInfo());
    echo "\n管理员:\n";
    print_r($admin->getUserInfo());
    echo "\nVIP用户:\n";
    print_r($vip->getUserInfo());

} catch (Exception $e) {
    echo "错误:" . $e->getMessage() . "\n";
}
?>

多层继承示例

<?php
// 基础类:员工
class Employee {
    protected $id;
    protected $name;
    protected $position;
    protected $salary;
    protected $hireDate;
    protected $department;

    public function __construct($name, $position, $salary, $department) {
        $this->id = uniqid('emp_');
        $this->name = $name;
        $this->position = $position;
        $this->salary = $salary;
        $this->department = $department;
        $this->hireDate = date('Y-m-d');

        echo "雇佣员工:{$this->name} ({$this->position})\n";
    }

    public function work() {
        echo "{$this->name} 正在工作\n";
    }

    public function takeBreak() {
        echo "{$this->name} 正在休息\n";
    }

    public function getAnnualSalary() {
        return $this->salary * 12;
    }

    public function getYearsOfService() {
        $hireDate = new DateTime($this->hireDate);
        $currentDate = new DateTime();
        return $currentDate->diff($hireDate)->y;
    }

    public function giveRaise($percentage) {
        $increase = $this->salary * ($percentage / 100);
        $this->salary += $increase;
        echo "{$this->name} 获得加薪:¥{$increase},新工资:¥{$this->salary}\n";
    }

    public function getEmployeeInfo() {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'position' => $this->position,
            'salary' => $this->salary,
            'department' => $this->department,
            'hire_date' => $this->hireDate,
            'years_of_service' => $this->getYearsOfService()
        ];
    }

    // Getter方法
    public function getId() { return $this->id; }
    public function getName() { return $this->name; }
    public function getPosition() { return $this->position; }
    public function getSalary() { return $this->salary; }
    public function getDepartment() { return $this->department; }
}

// 第二层:经理(继承员工)
class Manager extends Employee {
    private $teamSize;
    private $managedEmployees = [];
    private $bonus;

    public function __construct($name, $department, $salary, $teamSize = 0) {
        parent::__construct($name, "经理", $salary, $department);
        $this->teamSize = $teamSize;
        $this->bonus = 0;
    }

    public function addEmployee(Employee $employee) {
        $this->managedEmployees[] = $employee;
        $this->teamSize = count($this->managedEmployees);
        echo "经理 {$this->name} 现在管理 {$this->teamSize} 名员工\n";
    }

    public function removeEmployee($employeeId) {
        foreach ($this->managedEmployees as $key => $employee) {
            if ($employee->getId() === $employeeId) {
                unset($this->managedEmployees[$key]);
                $this->managedEmployees = array_values($this->managedEmployees);
                $this->teamSize = count($this->managedEmployees);
                echo "移除员工,当前团队规模:{$this->teamSize}\n";
                return true;
            }
        }
        return false;
    }

    public function conductMeeting() {
        echo "经理 {$this->name} 正在主持会议\n";
    }

    public function assignTask($task) {
        echo "经理 {$this->name} 分配任务:{$task}\n";
    }

    public function evaluatePerformance() {
        echo "经理 {$this->name} 正在进行绩效评估\n";
        $this->awardBonus(1000);
    }

    protected function awardBonus($amount) {
        $this->bonus += $amount;
        echo "经理 {$this->name} 获得奖金:¥{$amount}\n";
    }

    public function getTotalCompensation() {
        return $this->getAnnualSalary() + $this->bonus;
    }

    public function getTeamMembers() {
        return $this->managedEmployees;
    }

    public function getTeamSize() {
        return $this->teamSize;
    }

    // 重写父类方法
    public function work() {
        echo "经理 {$this->name} 正在管理工作\n";
        $this->conductMeeting();
    }

    public function getEmployeeInfo() {
        $info = parent::getEmployeeInfo();
        $info['team_size'] = $this->teamSize;
        $info['bonus'] = $this->bonus;
        $info['total_compensation'] = $this->getTotalCompensation();
        $info['managed_employees'] = array_map(function($emp) {
            return $emp->getName() . ' (' . $emp->getPosition() . ')';
        }, $this->managedEmployees);
        return $info;
    }
}

// 第三层:总监(继承经理)
class Director extends Manager {
    private $managedManagers = [];
    private $budget;
    private $stockOptions;

    public function __construct($name, $department, $salary, $budget = 1000000) {
        parent::__construct($name, $department, $salary);
        $this->position = "总监";
        $this->budget = $budget;
        $this->stockOptions = 0;
    }

    public function addManager(Manager $manager) {
        $this->managedManagers[] = $manager;
        $this->teamSize += $manager->getTeamSize() + 1; // +1 for the manager
        echo "总监 {$this->name} 现在管理 " . count($this->managedManagers) . " 名经理\n";
    }

    public function approveBudget($amount, $purpose) {
        if ($amount <= $this->budget) {
            $this->budget -= $amount;
            echo "总监 {$this->name} 批准预算:¥{$amount} 用于 {$purpose}\n";
            return true;
        } else {
            echo "预算不足,无法批准\n";
            return false;
        }
    }

    public function setCompanyStrategy() {
        echo "总监 {$this->name} 正在制定公司战略\n";
    }

    public function boardMeeting() {
        echo "总监 {$this->name} 参加董事会会议\n";
    }

    public function grantStockOptions($shares) {
        $this->stockOptions += $shares;
        echo "总监 {$this->name} 获得股票期权:{$shares} 股\n";
    }

    public function getTotalCompensation() {
        $baseCompensation = parent::getTotalCompensation();
        $stockValue = $this->stockOptions * 50; // 假设每股50元
        return $baseCompensation + $stockValue;
    }

    // 重写父类方法
    public function work() {
        echo "总监 {$this->name} 正在进行战略决策\n";
        $this->setCompanyStrategy();
        $this->boardMeeting();
    }

    public function getEmployeeInfo() {
        $info = parent::getEmployeeInfo();
        $info['position'] = '总监';
        $info['budget'] = $this->budget;
        $info['stock_options'] = $this->stockOptions;
        $info['managed_managers'] = array_map(function($manager) {
            return $manager->getName() . ' (经理)';
        }, $this->managedManagers);
        $info['total_team_size'] = $this->teamSize;
        return $info;
    }
}

// 使用多层继承
echo "=== 多层继承示例 ===\n";

echo "\n创建员工层级:\n";
$employee1 = new Employee("张三", "开发工程师", 8000, "技术部");
$employee2 = new Employee("李四", "测试工程师", 7000, "技术部");
$manager = new Manager("王五", "技术部", 15000);
$director = new Director("赵六", "技术部", 30000, 5000000);

echo "\n构建团队结构:\n";
$manager->addEmployee($employee1);
$manager->addEmployee($employee2);
$director->addManager($manager);

echo "\n模拟工作场景:\n";
$employee1->work();
$manager->work();
$director->work();

echo "\n绩效评估和奖金:\n";
$manager->evaluatePerformance();
$director->awardBonus(5000);
$director->grantStockOptions(1000);

echo "\n预算管理:\n";
$director->approveBudget(100000, "新项目开发");
$director->approveBudget(5000000, "设备采购");

echo "\n员工信息对比:\n";
echo "普通员工:\n";
print_r($employee1->getEmployeeInfo());
echo "\n经理:\n";
print_r($manager->getEmployeeInfo());
echo "\n总监:\n";
print_r($director->getEmployeeInfo());
?>

实际应用示例

电子商务系统中的继承

<?php
// 基础产品类
class Product {
    protected $id;
    protected $name;
    protected $price;
    protected $description;
    protected $category;
    protected $stock;
    protected $sku;
    protected $weight;
    protected $isActive = true;

    public function __construct($id, $name, $price, $category) {
        $this->id = $id;
        $this->name = $name;
        $this->price = $price;
        $this->category = $category;
        $this->sku = $this->generateSKU();
        $this->stock = 0;
        $this->weight = 0;
        $this->description = '';
    }

    protected function generateSKU() {
        return strtoupper(substr($this->name, 0, 3)) . '-' . $this->id;
    }

    public function setPrice($price) {
        $this->price = max(0, (float)$price);
    }

    public function setStock($stock) {
        $this->stock = max(0, (int)$stock);
    }

    public function setDescription($description) {
        $this->description = $description;
    }

    public function setWeight($weight) {
        $this->weight = max(0, (float)$weight);
    }

    public function getCalculatedPrice() {
        return $this->price;
    }

    public function getShippingWeight() {
        return $this->weight;
    }

    public function isInStock() {
        return $this->stock > 0 && $this->isActive;
    }

    public function activate() {
        $this->isActive = true;
    }

    public function deactivate() {
        $this->isActive = false;
    }

    public function getBasicInfo() {
        return [
            'id' => $this->id,
            'name' => $this->name,
            'sku' => $this->sku,
            'price' => $this->price,
            'category' => $this->category,
            'stock' => $this->stock,
            'is_active' => $this->isActive
        ];
    }

    // Getter方法
    public function getId() { return $this->id; }
    public function getName() { return $this->name; }
    public function getPrice() { return $this->price; }
    public function getSku() { return $this->sku; }
    public function getStock() { return $this->stock; }
}

// 物理产品类
class PhysicalProduct extends Product {
    private $dimensions;
    private $requiresShipping = true;
    private $shippingCost;

    public function __construct($id, $name, $price, $category, $dimensions = []) {
        parent::__construct($id, $name, $price, $category);
        $this->dimensions = $dimensions;
        $this->calculateShippingCost();
    }

    private function calculateShippingCost() {
        $baseCost = 10;
        $weightCost = $this->weight * 2;
        $this->shippingCost = $baseCost + $weightCost;
    }

    public function setDimensions($length, $width, $height) {
        $this->dimensions = [
            'length' => $length,
            'width' => $width,
            'height' => $height
        ];
        $this->calculateShippingCost();
    }

    public function getShippingCost() {
        return $this->requiresShipping ? $this->shippingCost : 0;
    }

    public function getCalculatedPrice() {
        return parent::getCalculatedPrice() + $this->getShippingCost();
    }

    public function getBasicInfo() {
        $info = parent::getBasicInfo();
        $info['type'] = 'physical';
        $info['dimensions'] = $this->dimensions;
        $info['shipping_cost'] = $this->getShippingCost();
        $info['total_price'] = $this->getCalculatedPrice();
        return $info;
    }
}

// 数字产品类
class DigitalProduct extends Product {
    private $fileSize;
    private $fileFormat;
    private $downloadLimit = 5;
    private $downloadExpire = '30 days';

    public function __construct($id, $name, $price, $category, $fileSize, $fileFormat) {
        parent::__construct($id, $name, $price, $category);
        $this->fileSize = $fileSize;
        $this->fileFormat = $fileFormat;
        $this->weight = 0; // 数字产品没有重量
    }

    public function setDownloadLimit($limit) {
        $this->downloadLimit = max(1, (int)$limit);
    }

    public function setDownloadExpire($days) {
        $this->downloadExpire = $days . ' days';
    }

    public function getShippingCost() {
        return 0; // 数字产品免运费
    }

    public function getCalculatedPrice() {
        return parent::getCalculatedPrice(); // 无运费
    }

    public function getBasicInfo() {
        $info = parent::getBasicInfo();
        $info['type'] = 'digital';
        $info['file_size'] = $this->fileSize;
        $info['file_format'] = $this->fileFormat;
        $info['download_limit'] = $this->downloadLimit;
        $info['download_expire'] = $this->downloadExpire;
        $info['total_price'] = $this->getCalculatedPrice();
        return $info;
    }
}

// 订阅产品类
class SubscriptionProduct extends Product {
    private $billingCycle;
    private $duration;
    private $autoRenew = true;
    private $trialDays = 0;

    public function __construct($id, $name, $price, $category, $billingCycle = 'monthly') {
        parent::__construct($id, $name, $price, $category);
        $this->billingCycle = $billingCycle;
        $this->duration = $this->calculateDuration();
        $this->weight = 0;
    }

    private function calculateDuration() {
        switch ($this->billingCycle) {
            case 'monthly': return 30;
            case 'quarterly': return 90;
            case 'yearly': return 365;
            default: return 30;
        }
    }

    public function setTrialDays($days) {
        $this->trialDays = max(0, (int)$days);
    }

    public function enableAutoRenew($enable = true) {
        $this->autoRenew = $enable;
    }

    public function getCalculatedPrice() {
        $monthlyPrice = parent::getCalculatedPrice();
        switch ($this->billingCycle) {
            case 'monthly': return $monthlyPrice;
            case 'quarterly': return $monthlyPrice * 3 * 0.9; // 10% 折扣
            case 'yearly': return $monthlyPrice * 12 * 0.8; // 20% 折扣
            default: return $monthlyPrice;
        }
    }

    public function getShippingCost() {
        return 0; // 订阅产品免运费
    }

    public function getBasicInfo() {
        $info = parent::getBasicInfo();
        $info['type'] = 'subscription';
        $info['billing_cycle'] = $this->billingCycle;
        $info['duration_days'] = $this->duration;
        $info['auto_renew'] = $this->autoRenew;
        $info['trial_days'] = $this->trialDays;
        $info['total_price'] = $this->getCalculatedPrice();
        return $info;
    }
}

// 使用电子商务产品继承
echo "=== 电子商务系统继承示例 ===\n";

echo "\n创建不同类型的产品:\n";
$laptop = new PhysicalProduct("P001", "笔记本电脑", 5000, "电子产品");
$laptop->setWeight(2.5);
$laptop->setDimensions(35, 25, 2);
$laptop->setStock(50);

$ebook = new DigitalProduct("D001", "PHP编程指南", 29.99, "电子书", "15MB", "PDF");
$ebook->setDownloadLimit(10);
$ebook->setStock(999999); // 数字产品库存不受限制

$vipSubscription = new SubscriptionProduct("S001", "VIP会员", 99, "会员服务", "monthly");
$vipSubscription->setTrialDays(7);

echo "\n产品信息对比:\n";
echo "物理产品:\n";
print_r($laptop->getBasicInfo());

echo "\n数字产品:\n";
print_r($ebook->getBasicInfo());

echo "\n订阅产品:\n";
print_r($vipSubscription->getBasicInfo());

echo "\n价格计算:\n";
echo "笔记本电脑总价(含运费):¥" . $laptop->getCalculatedPrice() . "\n";
echo "电子书价格:¥" . $ebook->getCalculatedPrice() . "\n";
echo "VIP会员年费:¥" . (new SubscriptionProduct("S002", "VIP年费", 99, "会员服务", "yearly"))->getCalculatedPrice() . "\n";
?>

最佳实践和注意事项

封装的最佳实践

  1. 最小暴露原则:只暴露必要的方法和属性
  2. 使用访问控制:合理使用public、protected、private
  3. 提供getter和setter:控制对私有属性的访问
  4. 验证输入:在setter方法中验证数据
  5. 保持接口简单:公共接口应该简洁明了

继承的最佳实践

  1. 遵循"is-a"关系:子类应该是父类的一种特殊类型
  2. 不要过度继承:优先使用组合而不是继承
  3. 调用父类构造函数:始终在子类构造函数中调用parent::__construct()
  4. 小心重写:重写方法时保持向后兼容性
  5. 了解层次深度:避免过深的继承层次

常见的反模式

<?php
// 反模式1:过度暴露
class BadClass {
    public $data; // 应该是private
    // 缺少getter/setter,直接暴露内部状态
}

// 反模式2:过度继承
class A extends B extends C extends D extends E {
    // 继承层次过深,难以维护
}

// 反模式3:违反"is-a"原则
class Employee extends DatabaseConnection {
    // 员工不是数据库连接,应该使用组合
}

// 好的设计模式
class GoodExample {
    private $data;

    public function getData() {
        return $this->data;
    }

    public function setData($data) {
        $this->data = $this->validateData($data);
    }

    private function validateData($data) {
        // 验证逻辑
        return $data;
    }
}

// 使用组合而不是继承
class Employee {
    private $dbConnection;

    public function __construct(DatabaseConnection $dbConnection) {
        $this->dbConnection = $dbConnection;
    }
}
?>

总结

封装和继承是面向对象编程的基石:

关键要点:

  1. 封装

    • 保护数据和控制访问
    • 使用访问控制修饰符
    • 提供公共接口
    • 实现信息隐藏
  2. 继承

    • 实现代码重用
    • 建立"is-a"关系
    • 支持方法重写
    • 创建类层次结构
  3. 访问控制

    • public:任何地方可访问
    • protected:类和子类可访问
    • private:仅类内部可访问
  4. 设计原则

    • 最小暴露原则
    • 封装变化
    • 优先组合而不是继承
    • 保持接口简单

最佳实践:

  • 合理使用访问控制修饰符
  • 通过getter和setter控制属性访问
  • 遵循"is-a"关系使用继承
  • 在子类中调用parent构造函数
  • 避免过深的继承层次
  • 优先考虑组合而不是继承

通过掌握封装和继承,你可以构建更加结构化、可维护和可扩展的面向对象应用程序。这些概念为更高级的OOP特性如接口、抽象类和多态奠定了基础。