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";
?>

构造函数的优势

  1. 自动执行:创建对象时自动调用
  2. 简化代码:一行代码完成对象创建和初始化
  3. 强制要求:确保对象有必要的初始数据

访问控制:保护对象的数据安全

想象你的房子有不同的区域:
客厅(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();   // 咪咪在喵喵叫(子类特有)
?>

继承的核心价值

  1. 代码复用:不用重复写相同功能
  2. 易于扩展:在父类基础上添加新功能
  3. 结构清晰:相关功能组织在一起

实战练习 – 图书管理系统

基础版:图书类

<?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编程状态变为"已借出"
?>