PHP 面向对象
本章将介绍 PHP 面向对象编程的核心概念,包括类、对象、继承、接口等。
类与对象
定义类
使用 class 关键字定义类:
<?php
class Person {
// 属性
public $name;
public $age;
// 构造方法
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
}
// 方法
public function greet() {
return "你好,我是" . $this->name;
}
// 析构方法
public function __destruct() {
echo "对象被销毁";
}
}
?>
创建对象
<?php
// 创建对象
$person = new Person("张三", 25);
// 访问属性
echo $person->name; // 张三
// 调用方法
echo $person->greet(); // 你好,我是张三
// PHP 8+ 无括号创建
$person = new Person;
?>
属性
<?php
class User {
// 公有属性(任何地方可访问)
public $name;
// 受保护属性(本类和子类可访问)
protected $email;
// 私有属性(仅本类可访问)
private $password;
// 静态属性
public static $count = 0;
// 类型声明属性(PHP 7.4+)
public int $age;
public string $city = "北京";
// 只读属性(PHP 8.1+)
public readonly string $id;
public function __construct(string $id) {
$this->id = $id;
self::$count++;
}
}
?>
方法
<?php
class Calculator {
// 公有方法
public function add($a, $b) {
return $a + $b;
}
// 受保护方法
protected function validate($num) {
return is_numeric($num);
}
// 私有方法
private function log($message) {
error_log($message);
}
// 静态方法
public static function multiply($a, $b) {
return $a * $b;
}
// 类型声明
public function divide(float $a, float $b): float {
return $a / $b;
}
}
// 调用静态方法
echo Calculator::multiply(3, 4); // 12
?>
$this 与 self
<?php
class Counter {
public $count = 0;
public static $total = 0;
public function increment() {
$this->count++; // 访问实例属性
self::$total++; // 访问静态属性
}
public static function getTotal() {
// return $this->count; // 错误!静态方法中不能使用 $this
return self::$total;
}
}
?>
构造与析构
构造方法
<?php
class User {
public $name;
public $age;
// PHP 8+ 构造器属性提升
public function __construct(
public string $username,
public string $email,
int $age = 18
) {
$this->age = $age;
}
}
$user = new User("张三", "[email protected]", 25);
echo $user->username; // 张三
?>
析构方法
<?php
class FileHandler {
private $file;
public function __construct($filename) {
$this->file = fopen($filename, "r");
}
public function __destruct() {
if ($this->file) {
fclose($this->file);
}
}
}
$handler = new FileHandler("test.txt");
// 当 $handler 被销毁或脚本结束时,析构方法自动调用
?>
继承
基本继承
<?php
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function speak() {
return "动物发出声音";
}
}
class Dog extends Animal {
public function speak() {
return $this->name . " 汪汪叫";
}
public function fetch() {
return $this->name . " 去捡球";
}
}
$dog = new Dog("旺财");
echo $dog->speak(); // 旺财 汪汪叫
echo $dog->fetch(); // 旺财 去捡球
?>
parent 关键字
<?php
class Student extends Person {
public $grade;
public function __construct($name, $age, $grade) {
parent::__construct($name, $age); // 调用父类构造方法
$this->grade = $grade;
}
public function greet() {
return parent::greet() . ",我是{$this->grade}年级学生";
}
}
?>
final 关键字
<?php
// final 类不能被继承
final class Singleton {
// ...
}
class BaseClass {
// final 方法不能被重写
final public function getId() {
return $this->id;
}
}
?>
抽象类
<?php
abstract class Shape {
protected $color;
public function __construct($color) {
$this->color = $color;
}
// 抽象方法必须由子类实现
abstract public function getArea();
// 普通方法
public function getColor() {
return $this->color;
}
}
class Rectangle extends Shape {
private $width;
private $height;
public function __construct($color, $width, $height) {
parent::__construct($color);
$this->width = $width;
$this->height = $height;
}
public function getArea() {
return $this->width * $this->height;
}
}
$rect = new Rectangle("红色", 10, 5);
echo $rect->getArea(); // 50
?>
接口
定义接口
<?php
interface Flyable {
public function fly(): void;
public function land(): void;
}
interface Swimmable {
public function swim(): void;
}
?>
实现接口
<?php
class Duck implements Flyable, Swimmable {
public function fly(): void {
echo "鸭子在飞";
}
public function land(): void {
echo "鸭子着陆";
}
public function swim(): void {
echo "鸭子在游泳";
}
}
?>
接口继承
<?php
interface Animal {
public function eat(): void;
}
interface Bird extends Animal {
public function layEggs(): void;
}
class Sparrow implements Bird {
public function eat(): void {
echo "麻雀吃虫子";
}
public function layEggs(): void {
echo "麻雀下蛋";
}
}
?>
Trait
定义和使用 Trait
<?php
trait Logger {
protected function log($message) {
echo "[LOG] $message\n";
}
}
trait Timestampable {
public $createdAt;
public $updatedAt;
public function touch() {
$this->updatedAt = new DateTime();
}
}
class User {
use Logger, Timestampable;
public function save() {
$this->touch();
$this->log("用户已保存");
}
}
?>
Trait 冲突解决
<?php
trait A {
public function say() {
echo "A\n";
}
}
trait B {
public function say() {
echo "B\n";
}
}
class MyClass {
use A, B {
B::say insteadof A; // 使用 B 的 say 方法
A::say as sayA; // 给 A 的 say 方法起别名
}
}
$obj = new MyClass();
$obj->say(); // B
$obj->sayA(); // A
?>
修改 Trait 方法可见性
<?php
trait HelloWorld {
public function sayHello() {
echo "Hello World!";
}
}
class MyClass {
use HelloWorld {
sayHello as private; // 改为私有
}
public function greet() {
$this->sayHello(); // 内部可调用
}
}
?>
抽象 Trait 方法
<?php
trait Validator {
// 要求使用类实现此方法
abstract protected function getRules(): array;
public function validate($data) {
$rules = $this->getRules();
// 验证逻辑...
}
}
class UserForm {
use Validator;
protected function getRules(): array {
return [
'name' => 'required',
'email' => 'required|email'
];
}
}
?>
静态成员
<?php
class Counter {
private static $count = 0;
public function __construct() {
self::$count++;
}
public static function getCount() {
return self::$count;
}
// 后期静态绑定
public static function create() {
return new static(); // 返回调用类的实例
}
}
class AdvancedCounter extends Counter {}
$c1 = new Counter();
$c2 = new Counter();
$c3 = new AdvancedCounter();
echo Counter::getCount(); // 3
// 后期静态绑定示例
$obj = AdvancedCounter::create();
echo get_class($obj); // AdvancedCounter
?>
常量
<?php
class Math {
// 类常量
const PI = 3.14159;
// PHP 8.3+ 支持类型声明
// const float PI = 3.14159;
public static function area($radius) {
return self::PI * $radius * $radius;
}
}
echo Math::PI; // 3.14159
echo Math::area(5); // 78.53975
?>
魔术方法
__get 和 __set
<?php
class DynamicProperties {
private $data = [];
public function __get($name) {
return $this->data[$name] ?? null;
}
public function __set($name, $value) {
$this->data[$name] = $value;
}
public function __isset($name) {
return isset($this->data[$name]);
}
public function __unset($name) {
unset($this->data[$name]);
}
}
$obj = new DynamicProperties();
$obj->name = "张三"; // 调用 __set
echo $obj->name; // 调用 __get,输出:张三
?>
__call 和 __callStatic
<?php
class MethodOverloading {
public function __call($name, $arguments) {
echo "调用不存在的方法:$name\n";
print_r($arguments);
}
public static function __callStatic($name, $arguments) {
echo "调用不存在的静态方法:$name\n";
print_r($arguments);
}
}
$obj = new MethodOverloading();
$obj->hello("world"); // 调用不存在的方法:hello
MethodOverloading::staticMethod(); // 调用不存在的静态方法:staticMethod
?>
__toString
<?php
class User {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function __toString() {
return "User: " . $this->name;
}
}
$user = new User("张三");
echo $user; // User: 张三
?>
__invoke
<?php
class Multiplier {
private $factor;
public function __construct($factor) {
$this->factor = $factor;
}
public function __invoke($value) {
return $value * $this->factor;
}
}
$double = new Multiplier(2);
echo $double(5); // 10(像函数一样调用对象)
?>
__clone
<?php
class Person {
public $name;
public $friends;
public function __construct($name) {
$this->name = $name;
$this->friends = [];
}
public function __clone() {
// 深拷贝
$this->friends = [];
}
}
$p1 = new Person("张三");
$p1->friends[] = "李四";
$p2 = clone $p1;
$p2->name = "王五";
echo $p1->name; // 张三
echo $p2->name; // 王五
?>
对象比较
<?php
class Point {
public $x;
public $y;
public function __construct($x, $y) {
$this->x = $x;
$this->y = $y;
}
}
$p1 = new Point(1, 2);
$p2 = new Point(1, 2);
$p3 = $p1;
// 比较是否是同一个对象
var_dump($p1 === $p2); // false
var_dump($p1 === $p3); // true
// 比较属性值
var_dump($p1 == $p2); // true
?>
小结
本章我们学习了:
- 类与对象:属性、方法、构造函数
- 继承:extends、parent、final、abstract
- 接口:定义和实现
- Trait:代码复用
- 静态成员:静态属性和方法
- 魔术方法:__get、__set、__call、__toString 等
下一章我们将学习文件操作。