PHP教程:类与对象
编辑文章面向对象编程(OOP)是PHP编程的核心概念之一,让我们用最简单的方式理解它。
基础解释
什么是类和对象
想象你要开发一个”学生管理系统”。每个学生都有姓名、年龄、成绩等特征,还能进行上课、考试等行为。
- 类 = 学生的”设计模板”或”蓝图”
- 对象 = 按照模板创建的”具体学生”
<?php
// 1. 设计模板(类)
class Student {
// 学生的特征(属性)
public $name;
public $age;
public $score;
// 学生的行为(方法)
public function attendClass() {
echo "{$this->name}正在上课";
}
}
// 2. 根据模板创建具体学生(对象)
$student1 = new Student(); // 第一个学生
$student2 = new Student(); // 第二个学生
// 3. 为每个学生设置不同特征
$student1->name = "张三";
$student1->age = 18;
$student1->score = 85;
$student2->name = "李四";
$student2->age = 19;
$student2->score = 90;
// 4. 让学生执行行为
$student1->attendClass(); // 输出:张三正在上课
$student2->attendClass(); // 输出:李四正在上课
?>
核心概念速记
| 概念 | 比喻 | PHP代码 | 说明 |
|---|---|---|---|
| 类 | 设计图纸 | class Student { } |
定义模板 |
| 对象 | 具体产品 | $stu = new Student() |
根据模板创建 |
| 属性 | 产品特征 | public $name; |
对象的特征(名词) |
| 方法 | 产品功能 | public function study() |
对象的行为(动词) |
| new | 生产指令 | new Student() |
“按照图纸制造一个” |
基础语法
完整的类定义
<?php
// 定义类:class 关键字 + 类名 + { }
class Product {
// 属性声明(特征)
public $name;
public $price;
// 方法定义(行为)
public function showInfo() {
return "商品:{$this->name},价格:{$this->price}元";
}
}
// 使用类创建对象
$phone = new Product(); // 创建第一个商品
$phone->name = "智能手机"; // 设置属性
$phone->price = 2999; // 设置属性
$book = new Product(); // 创建第二个商品
$book->name = "编程教材";
$book->price = 99;
// 调用方法
echo $phone->showInfo(); // 输出:商品:智能手机,价格:2999元
echo $book->showInfo(); // 输出:商品:编程教材,价格:99元
?>
理解$this关键字
$this 是类内部的一个特殊变量,永远指向当前对象。
<?php
class Person {
public $name;
public function sayHello() {
// 错误写法:echo $name; (这里找不到$name变量)
// 正确写法:使用$this指向当前对象
echo "你好,我是{$this->name}";
}
}
$p = new Person();
$p->name = "王五";
$p->sayHello(); // 输出:你好,我是王五
?>
记忆口诀:
– 在类外面操作对象:$对象名->属性名
– 在类里面操作对象:$this->属性名
构造函数:让对象创建更智能
每次都创建对象后再设置属性很麻烦。构造函数可以在创建对象时自动初始化属性。
传统方式 vs 构造函数方式
<?php
// 方式1:没有构造函数(繁琐)
class User1 {
public $username;
public $email;
}
$user1 = new User1();
$user1->username = "张三";
$user1->email = "zhangsan@example.com";
// 方式2:使用构造函数(简洁)
class User2 {
public $username;
public $email;
// 构造函数:创建对象时自动执行
public function __construct($name, $email) {
$this->username = $name;
$this->email = $email;
echo "创建了新用户:{$name}\n";
}
}
// 一步完成:创建对象 + 设置属性
$user2 = new User2("李四", "lisi@example.com");
echo "用户名:" . $user2->username . "\n";
echo "邮箱:" . $user2->email . "\n";
?>
构造函数的优势
- 自动执行:创建对象时自动调用
- 简化代码:一行代码完成对象创建和初始化
- 强制要求:确保对象有必要的初始数据
访问控制:保护对象的数据安全
想象你的房子有不同的区域:
– 客厅(public):谁都能进
– 卧室(protected):家人能进
– 保险箱(private):只有自己能开
三种访问权限
<?php
class BankAccount {
// public:公共区域,任何代码都能访问
public $accountNumber; // 账号(公开信息)
// protected:保护区域,只有自己和子类能访问
protected $balance; // 余额(敏感信息)
// private:私有区域,只有自己内部能访问
private $password; // 密码(绝密信息)
public function __construct($number, $initBalance, $pwd) {
$this->accountNumber = $number;
$this->balance = $initBalance;
$this->password = $pwd;
}
// 公开方法:查询余额(提供安全访问方式)
public function getBalance($inputPwd) {
if ($this->checkPassword($inputPwd)) {
return "当前余额:" . $this->balance . "元";
}
return "密码错误,无法查询";
}
// 私有方法:验证密码(内部使用,外部无法调用)
private function checkPassword($inputPwd) {
return $this->password === $inputPwd;
}
}
$account = new BankAccount("123456", 1000, "mypassword123");
// 可以访问public属性
echo "账号:" . $account->accountNumber . "\n"; // 输出:123456
// 不能直接访问protected属性(会报错)
// echo $account->balance; // 错误!
// 不能直接访问private属性(会报错)
// echo $account->password; // 错误!
// 通过公开方法安全访问
echo $account->getBalance("mypassword123") . "\n"; // 正确
echo $account->getBalance("wrongpassword") . "\n"; // 密码错误
?>
protected 涉及到类的继承,文章后面部分我们再展开讨论。刚开始学习时,可以全部使用 public。等熟练基本概念后,再学习使用 private 和 protected 来保护数据。
静态成员:属于整个类的功能
有些东西不属于某个具体对象,而是属于整个”类别”。
普通成员 vs 静态成员
<?php
class Counter {
// 普通属性:每个对象独立拥有
public $id;
// 静态属性:整个类共享一个
public static $totalCount = 0;
public function __construct() {
// 每创建一个对象,总数加1
self::$totalCount++; // 访问静态属性
$this->id = self::$totalCount; // 赋给普通属性
}
// 静态方法:通过类名直接调用
public static function showTotal() {
echo "当前共有 " . self::$totalCount . " 个计数器\n";
}
// 普通方法:需要对象调用
public function showId() {
echo "我的ID是:{$this->id}\n";
}
}
// 静态方法:不需要创建对象就能调用
Counter::showTotal(); // 输出:当前共有 0 个计数器
// 创建对象
$c1 = new Counter();
$c2 = new Counter();
$c3 = new Counter();
// 再次查看总数(静态属性被所有对象共享)
Counter::showTotal(); // 输出:当前共有 3 个计数器
// 每个对象有自己的ID(普通属性每个对象独立)
$c1->showId(); // 我的ID是:1
$c2->showId(); // 我的ID是:2
$c3->showId(); // 我的ID是:3
?>
静态成员使用要点
| 类型 | 如何定义 | 如何访问 | 属于 |
|---|---|---|---|
| 普通属性 | public $id; |
$对象->id |
对象 |
| 静态属性 | public static $total; |
类名::$total |
类 |
| 普通方法 | public function show(){} |
$对象->show() |
对象 |
| 静态方法 | public static function show(){} |
类名::show() |
类 |
记忆技巧:看到 static 就用 ::,看不到 static 就用 ->
继承:代码复用和扩展
子类可以继承父类的所有功能,并添加自己的新功能。
基础继承示例
<?php
// 父类:动物(基础功能)
class Animal {
public $name;
public function __construct($name) {
$this->name = $name;
}
public function eat() {
echo "{$this->name}在吃东西\n";
}
public function sleep() {
echo "{$this->name}在睡觉\n";
}
}
// 子类:狗(继承动物并扩展)
class Dog extends Animal {
// 子类特有的方法
public function bark() {
echo "{$this->name}在汪汪叫\n";
}
// 重写父类方法(改进父类功能)
public function eat() {
parent::eat(); // 先执行父类的eat方法
echo "{$this->name}吃的是狗粮\n";
}
}
// 子类:猫(继承动物并扩展)
class Cat extends Animal {
public function meow() {
echo "{$this->name}在喵喵叫\n";
}
}
// 使用继承
$dog = new Dog("旺财");
$dog->eat(); // 输出:旺财在吃东西\n旺财吃的是狗粮
$dog->sleep(); // 旺财在睡觉(继承自父类)
$dog->bark(); // 旺财在汪汪叫(子类特有)
$cat = new Cat("咪咪");
$cat->eat(); // 咪咪在吃东西(继承自父类)
$cat->meow(); // 咪咪在喵喵叫(子类特有)
?>
继承的核心价值
- 代码复用:不用重复写相同功能
- 易于扩展:在父类基础上添加新功能
- 结构清晰:相关功能组织在一起
实战练习 – 图书管理系统
基础版:图书类
<?php
class Book {
// 属性
public $title;
public $author;
public $price;
private $isBorrowed = false; // 私有属性:是否被借出
// 构造函数
public function __construct($title, $author, $price) {
$this->title = $title;
$this->author = $author;
$this->price = $price;
}
// 方法:借书
public function borrow() {
if ($this->isBorrowed) {
echo "《{$this->title}》已被借出\n";
} else {
$this->isBorrowed = true;
echo "成功借出《{$this->title}》\n";
}
}
// 方法:还书
public function returnBook() {
$this->isBorrowed = false;
echo "《{$this->title}》已归还\n";
}
// 方法:显示图书信息
public function getInfo() {
$status = $this->isBorrowed ? "已借出" : "可借阅";
return "《{$this->title}》- {$this->author},价格:{$this->price}元,状态:{$status}";
}
}
// 使用图书类
$book1 = new Book("PHP编程", "张三", 59.9);
$book2 = new Book("JavaScript入门", "李四", 49.9);
echo $book1->getInfo() . "\n"; // 显示信息
$book1->borrow(); // 借书
echo $book1->getInfo() . "\n"; // 状态变为"已借出"
$book1->returnBook(); // 还书
echo $book1->getInfo() . "\n"; // 状态变回"可借阅"
?>
增强版:图书馆管理系统
<?php
// 图书馆类(使用静态成员管理所有图书)
class Library {
// 静态属性:存储所有图书
private static $allBooks = [];
// 静态方法:添加图书
public static function addBook($book) {
self::$allBooks[] = $book;
echo "添加图书成功,当前共有 " . count(self::$allBooks) . " 本书\n";
}
// 静态方法:显示所有图书
public static function showAllBooks() {
if (empty(self::$allBooks)) {
echo "图书馆暂无藏书\n";
return;
}
echo "=== 图书馆藏书清单 ===\n";
foreach (self::$allBooks as $index => $book) {
echo ($index + 1) . ". " . $book->getInfo() . "\n";
}
echo "=====================\n";
}
// 静态方法:借书
public static function borrowBook($title) {
foreach (self::$allBooks as $book) {
if ($book->title === $title) {
$book->borrow();
return;
}
}
echo "未找到图书:《{$title}》\n";
}
}
// 使用图书馆系统
$book1 = new Book("PHP编程", "张三", 59.9);
$book2 = new Book("JavaScript入门", "李四", 49.9);
$book3 = new Book("MySQL数据库", "王五", 69.9);
// 添加图书到图书馆
Library::addBook($book1);
Library::addBook($book2);
Library::addBook($book3);
// 显示所有图书
Library::showAllBooks();
// 借书操作
Library::borrowBook("PHP编程");
Library::showAllBooks(); // PHP编程状态变为"已借出"
?>