「PHP系列」PHP面向对象详解

04-14 1584阅读

文章目录

  • 一、PHP面向对象
    • 1. 类(Class)
    • 2. 对象(Object)
    • 3. 构造函数和析构函数
    • 4. 访问修饰符
    • 5. 继承(Inheritance)
    • 6. 接口(Interface)
    • 7. 抽象类(Abstract Class)
    • 二、常见问题
      • 1. 构造函数相关问题
      • 2. 访问属性或方法时出错
      • 3. 继承中的方法重写问题
      • 4. 对象克隆问题
      • 三、相关链接

        一、PHP面向对象

        PHP 是一种广泛使用的服务器端脚本语言,它支持面向对象的编程(OOP)范式。面向对象编程是一种编程方法,它使用“对象”来设计应用程序和软件。在面向对象的 PHP 中,你可以创建类来定义对象的结构和行为,然后创建这些类的对象来执行特定的任务。

        「PHP系列」PHP面向对象详解
        (图片来源网络,侵删)

        1. 类(Class)

        类是一个模板,它定义了对象的属性和方法。属性是对象的特性,而方法是对象可以执行的操作。

        class Car {
            public $color;
            public $brand;
            public function startEngine() {
                echo "Engine started!";
            }
        }
        

        2. 对象(Object)

        对象是类的实例。你可以使用 new 关键字来创建类的对象。

        $myCar = new Car();
        $myCar->color = "Red";
        $myCar->brand = "Toyota";
        $myCar->startEngine(); // 输出 "Engine started!"
        

        3. 构造函数和析构函数

        • 构造函数:在创建对象时自动调用的方法,通常用于初始化对象的属性。
        • 析构函数:在对象不再需要时自动调用的方法,通常用于执行清理操作。
          class Car {
              public $color;
              public function __construct() {
                  echo "Car created!";
              }
              public function __destruct() {
                  echo "Car destroyed!";
              }
          }
          

          4. 访问修饰符

          PHP 提供了三种访问修饰符:public、protected 和 private。它们决定了类属性和方法的可见性。

          • public:属性和方法可以从任何地方访问。
          • protected:属性和方法只能在其定义的类及其子类中访问。
          • private:属性和方法只能在其定义的类中访问。

            5. 继承(Inheritance)

            继承允许一个类(子类)继承另一个类(父类)的属性和方法。这有助于减少代码冗余并促进代码重用。

            class Car {
                public function startEngine() {
                    echo "Engine started!";
                }
            }
            class ElectricCar extends Car {
                public function rechargeBattery() {
                    echo "Battery recharged!";
                }
            }
            $myElectricCar = new ElectricCar();
            $myElectricCar->startEngine(); // 继承自 Car 类的方法
            $myElectricCar->rechargeBattery(); // ElectricCar 类特有的方法
            

            6. 接口(Interface)

            接口定义了一组方法的契约,类可以实现这些接口以确保它们遵循特定的结构。

            interface Vehicle {
                public function startEngine();
            }
            class Car implements Vehicle {
                public function startEngine() {
                    echo "Car engine started!";
                }
            }
            

            7. 抽象类(Abstract Class)

            抽象类不能被实例化,但可以作为其他类的基类。抽象类可以包含抽象方法,这些方法必须在任何继承该抽象类的子类中实现。

            abstract class Car {
                public function startEngine() {
                    echo "Engine started!";
                }
                abstract public function getSpecs();
            }
            class SportsCar extends Car {
                public function getSpecs() {
                    echo "High-performance specs!";
                }
            }
            

            二、常见问题

            1. 构造函数相关问题

            问题:忘记在类定义中提供构造函数,或者构造函数的命名不正确。

            案例代码:

            class Person {
                public $name;
                // 错误的构造函数命名
                public function Person($name) {
                    $this->name = $name;
                }
            }
            $person = new Person('John'); // 抛出错误,因为构造函数命名错误
            

            解决方案:确保构造函数的命名与类名完全相同,并且没有返回类型声明。

            class Person {
                public $name;
                // 正确的构造函数
                public function __construct($name) {
                    $this->name = $name;
                }
            }
            $person = new Person('John'); // 正确创建对象
            

            2. 访问属性或方法时出错

            问题:尝试访问一个不存在的属性或方法,或者访问权限不足。

            案例代码:

            class User {
                private $password;
                public function setPassword($password) {
                    $this->password = $password;
                }
                // 没有提供获取密码的方法
            }
            $user = new User();
            $user->setPassword('secret');
            echo $user->password; // 抛出错误,因为$password是私有的
            

            解决方案:确保属性或方法存在,并且具有正确的访问权限。如果需要访问私有属性,应提供公共的getter方法。

            class User {
                private $password;
                public function setPassword($password) {
                    $this->password = $password;
                }
                public function getPassword() {
                    return $this->password;
                }
            }
            $user = new User();
            $user->setPassword('secret');
            echo $user->getPassword(); // 正确获取密码,通过getter方法
            

            3. 继承中的方法重写问题

            问题:在子类中重写父类方法时,访问修饰符的限制可能导致问题。

            案例代码:

            class Animal {
                public function makeSound() {
                    echo "The animal makes a sound.";
                }
            }
            class Dog extends Animal {
                // 试图将父类的public方法重写为protected
                protected function makeSound() {
                    echo "The dog barks.";
                }
            }
            $dog = new Dog();
            $dog->makeSound(); // 抛出错误,因为makeSound()在Dog类中是protected的
            

            解决方案:在子类中重写父类方法时,应保持或放宽访问修饰符的限制。如果父类方法是public的,子类方法也应该是public的。

            class Dog extends Animal {
                // 正确重写父类方法,保持为public
                public function makeSound() {
                    echo "The dog barks.";
                }
            }
            $dog = new Dog();
            $dog->makeSound(); // 正确输出:The dog barks.
            

            4. 对象克隆问题

            问题:克隆对象时未正确处理对象内部的引用或资源。

            案例代码:

            class FileHandler {
                private $file;
                public function __construct($filename) {
                    $this->file = fopen($filename, 'r');
                }
                public function __clone() {
                    // 没有处理$file的克隆,导致两个对象共享同一个文件句柄
                }
            }
            $handler1 = new FileHandler('file.txt');
            $handler2 = clone $handler1;
            fclose($handler2->file); // 关闭handler2的文件句柄,也影响了handler1
            

            解决方案:在__clone方法中,正确处理需要克隆的资源或属性。

            class FileHandler {
                private $file;
                public function __construct($filename) {
                    $this->file = fopen($filename, 'r');
                }
                public function __clone() {
                    // 克隆文件句柄或重新打开文件
                    $this->file = fopen($this->file, 'r');
                }
                public function __destruct() {
                    fclose($this->file);
                }
            }
            $handler1 = new FileHandler('file1.txt');
            $handler2 = clone $handler1;
            

            三、相关链接

            1. php官网
            2. php_Github
            3. PHP实现Token
            4. 「PHP系列」PHP简介与起步
            5. 「PHP系列」PHP语法介绍
            6. 「PHP系列」PHP变量
            7. 「PHP系列」PHP echo/print语句、数据类型详解
            8. 「PHP系列」PHP 常量/字符串、类型比较
            9. 「PHP系列」PHP 运算符详解
            10. 「PHP系列」If…Else语句/switch语句
            11. 「PHP系列」数组详解
            12. 「PHP系列」PHP数组排序及运用场景
VPS购买请点击我

文章版权声明:除非注明,否则均为主机测评原创文章,转载或复制请以超链接形式并注明出处。

目录[+]