PHP 面向对象
面向对象(Object-Oriented,简称 OO)是一种以 "对象" 为核心的编程思想,它将数据和操作数据的方法封装在一起,通过对象间的交互完成程序功能。这种编程范式强调封装、继承、多态等特性,能显著提升代码的可扩展性、可维护性和可重用性。
在面向对象编程(OOP)中,对象是对现实世界实体的抽象,它由 "数据" 和 "行为" 共同组成。现实世界中的一切事物都可以视为对象,如计算机、汽车、动物等。
✅ 对象的主要三个特性:
- 对象的行为:对象可以执行的操作,如 "开灯"、"跑步"、"计算" 等。
- 对象的形态:对象在不同行为下的表现和属性,如颜色、尺寸、状态等。
- 对象的标识:区分同类对象的唯一标识,如同类汽车的车牌号。
例如,"动物" 是一个抽象概念,而 "狗" 和 "猫" 则是具体对象,它们有颜色属性,能跑能叫(行为),但通过品种、名字等标识区分彼此。
面向对象编程的核心特性
1. 封装(Encapsulation)
封装是将对象的属性和方法捆绑在一起,通过访问控制限制外部直接访问内部状态。
✅ PHP 通过三种访问修饰符实现封装:
public
(公有):可在任何地方访问。protected
(受保护):仅在自身及子类、父类中访问。private
(私有):仅在定义它的类中访问。
封装使对象的实现细节隐藏,仅通过公开接口与外部交互,提高了代码安全性。
2. 继承(Inheritance)
继承允许创建新类(子类)继承现有类(父类)的属性和方法,并可添加新功能或重写现有方法。
✅ PHP 使用extends
关键字实现单继承:
class ChildClass extends ParentClass {
// 子类代码
}
继承实现了代码复用,建立了类之间的层次关系,使系统更易于扩展。
3. 多态(Polymorphism)
多态性是指相同的函数或方法可作用于多种类型的对象上并获得不同的结果。不同的对象,收到同一消息可以产生不同的结果,这种现象称为多态性。
在 PHP 中,多态主要通过接口和抽象类实现,使代码更加灵活通用。
PHP 类(Class)
类是对一类事物的抽象描述,用于创建对象,它定义了对象的结构特征(属性)和行为特征(方法)。
class Person {
// 属性 (Properties)
public $name;
public $age;
// 方法 (Methods)
public function greet() {
return "Hello, my name is " . $this->name;
}
public function setAge($age) {
$this->age = $age;
}
}
✅ 类的基本组成部分:
- 属性 - 类的变量
- 方法 - 类的函数
- 构造函数 - 对象创建时自动调用的特殊方法
- 析构函数 - 对象销毁时自动调用的特殊方法
PHP 对象(Object)
对象是类的实例。使用new
关键字创建对象。
// 创建 Person 类的对象
$person1 = new Person();
// 设置属性
$person1->name = "Alice";
$person1->setAge(30);
// 调用方法
echo $person1->greet();
输出结果:
Hello, my name is Alice
PHP 成员变量(属性)
成员变量也称为属性,是类中定义的变量,用于存储对象的状态。
class Person {
// 成员变量(属性)
public $name;
protected $age;
private $email;
// 常量也是类成员的一部分
const SPECIES = 'Human';
}
✅ 成员变量特点:
- 必须使用访问修饰符:
public
、protected
或private
。 - 可以设置默认值。
- 通过
$this->变量名
在类内部访问。 - 通过
$对象->变量名
在类外部访问(仅限public
属性)。
PHP 成员函数(方法)
成员函数也称为方法,是类中定义的函数,用于定义对象的行为。
class Person {
// 成员变量
private $name;
// 成员函数(方法)
public function setName($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
// 静态方法
public static function sayHello() {
echo "Hello!";
}
}
✅ 成员函数特点:
- 可以有不同的访问修饰符:
public
、protected
或private
。 - 通过
$this
关键字访问当前对象的成员。 - 可以接受参数并返回值。
- 通过
$对象->方法名()
调用。
PHP 继承、父类、子类
继承是面向对象编程的核心特性之一,它允许一个类(子类)继承另一个类(父类)的属性和方法,从而实现代码复用和扩展。
class Vehicle {
public $brand;
public $color;
public function __construct($brand, $color) {
$this->brand = $brand;
$this->color = $color;
}
public function startEngine() {
echo "Engine started!";
}
}
class Car extends Vehicle {
public $numDoors;
public function __construct($brand, $color, $numDoors) {
parent::__construct($brand, $color); // 调用父类构造函数
$this->numDoors = $numDoors;
}
public function openTrunk() {
echo "Trunk opened!";
}
// 方法重写
public function startEngine() {
echo "Car engine started with a key!";
}
}
// 使用子类
$myCar = new Car("Toyota", "Red", 4);
$myCar->startEngine(); // 输出: Car engine started with a key!
$myCar->openTrunk(); // 输出: Trunk opened!
✅ 继承的重要特性
1. 访问修饰符的影响
public
:可在任何地方访问。protected
:可在类内部和子类中访问。private
:只能在定义它的类中访问。
2. 方法重写
- 子类可以重写父类的方法。
- 要保持方法签名一致(参数数量和类型)。
- 访问权限不能比父类更严格。
3. parent
关键字
- 用于在子类中访问父类的方法或属性。
- 常用于调用父类构造函数。
4. final
关键字
- 可以防止方法被重写或类被继承。
final public function myMethod() {...}
final class MyClass {...}
PHP 多态(Polymorphism)
多态性是指相同的函数或方法可作用于多种类型的对象上并获得不同的结果。
✅ 多态主要有两种实现方式:
1. 方法重写(覆盖)实现多态
class Animal {
public function makeSound() {
echo "动物发出声音";
}
}
class Dog extends Animal {
public function makeSound() {
echo "汪汪汪!";
}
}
class Cat extends Animal {
public function makeSound() {
echo "喵喵喵!";
}
}
function animalSound(Animal $animal) {
$animal->makeSound();
}
$dog = new Dog();
$cat = new Cat();
animalSound($dog); // 输出: 汪汪汪!
animalSound($cat); // 输出: 喵喵喵!
2. 接口实现多态
interface Shape {
public function calculateArea();
}
class Circle implements Shape {
private $radius;
public function __construct($radius) {
$this->radius = $radius;
}
public function calculateArea() {
return pi() * pow($this->radius, 2);
}
}
class Rectangle implements Shape {
private $width;
private $height;
public function __construct($width, $height) {
$this->width = $width;
$this->height = $height;
}
public function calculateArea() {
return $this->width * $this->height;
}
}
function printArea(Shape $shape) {
echo "面积: " . $shape->calculateArea() . "\n";
}
$circle = new Circle(5);
$rectangle = new Rectangle(4, 6);
printArea($circle); // 输出圆的面积
printArea($rectangle); // 输出矩形的面积
✅ PHP 多态的特点:
- 类型提示:可以使用父类或接口作为类型提示,接受任何子类或实现类的对象。
- 动态绑定:PHP在运行时确定调用哪个类的方法。
- 灵活性:增加新类时不需要修改使用多态的代码。
PHP 重载(Overloading)
重载是指函数或者方法有同样的名称,但是参数列表不相同,这种同名不同参数的函数或者方法之间,互相称之为重载函数或者方法。
PHP 重载指的是动态地 "创建" 类属性和方法,主要通过魔术方法来实现。与其他面向对象语言(如 Java 或 C++)中的概念有所不同。
1. 属性重载(动态属性)
PHP 通过以下魔术方法实现属性重载:
class User {
private $data = []; // 用来存储动态属性
// 当给不存在的属性赋值时,自动调用
public function __set($name, $value) {
$this->data[$name] = $value;
}
// 当读取不存在的属性时,自动调用
public function __get($name) {
return $this->data[$name] ?? null;
}
}
$user = new User();
$user->name = "张三"; // 本来没有 name 属性,但 __set 会接管
echo $user->name; // 输出 "张三",__get 会接管
2. 方法重载(动态方法)
PHP 通过以下魔术方法实现属性重载:
class DynamicMethods {
// 当调用不存在的方法时,自动调用
public function __call($method, $args) {
echo "你调用了方法: $method, 参数是: " . implode(", ", $args) . "\n";
}
// 静态方法版本(调用不存在的静态方法时触发)
public static function __callStatic($method, $args) {
echo "你调用了静态方法: $method, 参数是: " . implode(", ", $args) . "\n";
}
}
$obj = new DynamicMethods();
$obj->sayHello("PHP", "世界"); // 输出:你调用了方法: sayHello, 参数是: PHP, 世界
DynamicMethods::staticMethod("测试"); // 输出:你调用了静态方法: staticMethod, 参数是: 测试
PHP 封装(Encapsulation)
封装指的是将数据(属性)和操作数据的方法(函数)捆绑在一起,并对外部隐藏对象的内部实现细节。
✅ PHP 实现封装的方式:
1. 访问修饰符
PHP 使用访问修饰符来控制属性和方法的可见性:
class BankAccount {
// 私有属性,只能在类内部访问
private $balance = 0;
// 受保护的属性,可以在类和子类中访问
protected $accountNumber;
// 公共方法,可以从任何地方访问
public function deposit($amount) {
if ($amount > 0) {
$this->balance += $amount;
}
}
public function withdraw($amount) {
if ($amount > 0 && $amount <= $this->balance) {
$this->balance -= $amount;
return $amount;
}
return 0;
}
// 公共方法访问私有属性
public function getBalance() {
return $this->balance;
}
}
2. Getter 和 Setter 方法
通过公共方法来访问和修改私有属性:
class User {
private $name;
private $age;
// Getter方法
public function getName() {
return $this->name;
}
// Setter方法
public function setName($name) {
$this->name = trim($name);
}
public function getAge() {
return $this->age;
}
public function setAge($age) {
if ($age >= 0 && $age <= 120) {
$this->age = $age;
}
}
}
3. 魔术方法(Magic Methods)
PHP 提供了__get()
和__set()
等魔术方法来实现更灵活的属性访问控制:
class Product {
private $data = [];
public function __set($name, $value) {
if ($name === 'price' && $value < 0) {
throw new Exception("Price cannot be negative");
}
$this->data[$name] = $value;
}
public function __get($name) {
if (array_key_exists($name, $this->data)) {
return $this->data[$name];
}
return null;
}
public function __isset($name) {
return isset($this->data[$name]);
}
}
✅ PHP 封装的主要特性:
- 保护数据完整性:防止外部代码直接访问和修改对象的内部状态
- 隐藏实现细节:只暴露必要的接口,内部实现可以随时改变而不影响外部代码
- 简化使用:使用者只需要知道如何使用接口,不需要了解内部工作原理
✅ PHP 封装的主要优势:
- 控制访问:可以精确控制哪些属性/方法可以被外部访问
- 数据验证:在
setter
方法中可以添加验证逻辑 - 灵活性:可以修改内部实现而不影响外部代码
- 安全性:防止外部代码意外或恶意修改对象状态
构造函数和析构函数
构造函数在对象创建时自动调用,用于初始化对象状态。析构函数在对象销毁时自动调用,用于清理资源。
class Person {
public $name;
public $age;
// 构造函数
public function __construct($name, $age) {
$this->name = $name;
$this->age = $age;
echo "Person $name created.
";
}
// 析构函数
public function __destruct() {
echo "Person $this->name is being destroyed.
";
}
}
// 创建对象时会自动调用构造函数
$person2 = new Person("Bob", 25);
// 当脚本结束或对象被销毁时,析构函数会自动调用
反馈提交成功
感谢您的反馈,我们将尽快处理您的反馈