抽象类与接口
抽象类和接口是实现多态和规范子类行为的重要机制
php
<?php
// 抽象类 - 不能被实例化,只能被继承
abstract class Animal {
protected $name;
public function __construct($name) {
$this->name = $name;
}
// 抽象方法 - 没有方法体,必须在子类中实现
abstract public function makeSound();
// 普通方法
public function getName() {
return $this->name;
}
}
// 接口 - 定义规范,可以被多个类实现
interface Pet {
public function play();
public function feed();
}
// 接口可以继承其他接口
interface ShowPet extends Pet {
public function performTrick();
}
// 类可以实现多个接口,但只能继承一个抽象类
class Dog extends Animal implements ShowPet {
public function makeSound() {
return "汪汪!";
}
public function play() {
return "狗在玩球";
}
public function feed() {
return "喂狗粮";
}
public function performTrick() {
return "狗在表演技巧";
}
}
class Cat extends Animal implements Pet {
public function makeSound() {
return "喵喵!";
}
public function play() {
return "猫在玩毛线球";
}
public function feed() {
return "喂猫粮";
}
}
$dog = new Dog("大黄");
$cat = new Cat("小花");
echo $dog->getName() . "说: " . $dog->makeSound() . "\n"; // 大黄说: 汪汪!
echo $dog->performTrick() . "\n"; // 狗在表演技巧
echo $cat->getName() . "说: " . $cat->makeSound() . "\n"; // 小花说: 喵喵!
// 类型检查
function petSound(Animal $animal) {
echo $animal->getName() . "发出声音: " . $animal->makeSound() . "\n";
}
petSound($dog); // 大黄发出声音: 汪汪!
petSound($cat); // 小花发出声音: 喵喵!
// 接口类型检查
function interactWithPet(Pet $pet) {
echo $pet->play() . "\n";
echo $pet->feed() . "\n";
}
interactWithPet($dog); // 狗在玩球 \n 喂狗粮
interactWithPet($cat); // 猫在玩毛线球 \n 喂猫粮Trait 特性
Trait 是 PHP 5.4 引入的特性,用于解决单继承语言的局限性
php
<?php
// 可复用的代码单元
trait Loggable {
public function log($message) {
echo "Log: " . $message . "\n";
}
private function formatLogMessage($message) {
return "[" . date('Y-m-d H:i:s') . "] " . $message;
}
}
trait Cacheable {
public function cache($key, $value) {
echo "Caching $key\n";
// 实际应用中这里会保存到缓存系统
return true;
}
public function getFromCache($key) {
echo "Getting $key from cache\n";
// 实际应用中这里会从缓存系统获取
return null;
}
}
class Database {
use Loggable, Cacheable {
// 解决方法冲突
Loggable::log insteadof Cacheable;
Cacheable::log as cacheLog;
}
public function query($sql) {
$this->log("Executing query: $sql");
// 实际查询代码...
return [];
}
}
class UserRepository {
use Loggable;
public function findUser($id) {
$this->log("Finding user with ID: $id");
// 实际查找代码...
return ["id" => $id, "name" => "User $id"];
}
}
$db = new Database();
$db->query("SELECT * FROM users");
$db->cache("user_1", ["name" => "张三"]);
// 由于方法名冲突,我们使用别名
// $db->log("Database log"); // 使用Loggable的log
// $db->cacheLog("Cache log"); // 使用Cacheable的log的别名
$repo = new UserRepository();
$repo->findUser(1);
// Trait 的可见性
trait VisibleTrait {
public function publicMethod() {
return "Public method";
}
protected function protectedMethod() {
return "Protected method";
}
private function privateMethod() {
return "Private method";
}
// Trait 中可以使用抽象方法
abstract public function abstractMethod();
// Trait 中可以使用静态方法
public static function staticMethod() {
return "Static method";
}
}
class MyClass {
use VisibleTrait;
// 必须实现 Trait 中定义的抽象方法
public function abstractMethod() {
return "Implemented abstract method";
}
}
$obj = new MyClass();
echo $obj->publicMethod() . "\n"; // Public method
// echo $obj->protectedMethod(); // 无法在类外部访问
// echo $obj->privateMethod(); // 无法在类外部访问
echo $obj->abstractMethod() . "\n"; // Implemented abstract method
echo MyClass::staticMethod() . "\n"; // Static method