0

0

PHP面向对象编程:正确使用构造函数与区分继承和组合

霞舞

霞舞

发布时间:2025-09-27 09:45:48

|

875人浏览过

|

来源于php中文网

原创

php面向对象编程:正确使用构造函数与区分继承和组合

在PHP面向对象编程中,当遇到对象属性输出NULL值的问题时,通常是由于构造函数未正确定义或继承关系被错误使用。本文将深入探讨如何正确使用__construct方法初始化对象,并辨析“is-a”(继承)与“has-a”(组合)关系,避免不当的类设计,从而确保对象属性能够被正确赋值和访问。

1. 理解PHP中的构造函数 __construct

在PHP中,构造函数是一个特殊的方法,当一个新对象被创建时(通过new关键字),它会自动被调用。构造函数的主要作用是初始化对象的属性,确保对象在被使用前处于一个有效的状态。PHP中构造函数的标准命名是 __construct()。

原代码问题分析: 在提供的原始代码中,Patient类定义了一个名为record的方法来设置患者信息:

class Patient{
    private $name;
    private $age;
    private $gender;

    public function record($name, $age, $gender){ // 这是一个普通方法
        $this->name = $name;
        $this->age = $age;
        $this->gender = $gender;
    }   
    // ... getter methods
}

然而,在Clinic类的assignPatient方法中,创建Patient对象时却使用了new Patient($name, $age, $gender):

class Clinic extends Patient{
    // ...
    public function assignPatient($name, $age, $gender){
        $this->patients[] = new Patient($name, $age, $gender); // 尝试通过构造函数传参
    }
    // ...
}

当new Patient($name, $age, $gender)被调用时,PHP会尝试寻找Patient类的构造函数__construct来接收这些参数。由于Patient类中没有定义__construct,这些参数实际上并未被传递给任何方法来初始化属性,导致新创建的Patient对象其$name, $age, $gender属性保持未初始化状态,即为NULL。

解决方案:重命名为 __construct 将Patient类中的record方法重命名为__construct,使其成为真正的构造函数。

name = $name;
        $this->age = $age;
        $this->gender = $gender;
    }   

    public function getName(){
        return $this->name;
    }

    public function getAge(){
        return $this->age;
    }

    public function getGender(){
        return $this->gender;
    }
}

这样,当执行new Patient("Patrick star", 18, "Male")时,__construct方法会被自动调用,并正确地初始化$name, $age, $gender属性。

立即学习PHP免费学习笔记(深入)”;

2. 区分继承 (Inheritance) 与 组合 (Composition)

面向对象设计中的两个核心概念是继承和组合。正确选择它们对于构建健壮、可维护的代码至关重要。

BGremover
BGremover

VanceAI推出的图片背景移除工具

下载
  • 继承 (Inheritance) - "is-a" 关系: 当一个类(子类)是另一个类(父类)的特殊类型时,使用继承。例如,Dog extends Animal(狗是一种动物)。子类会继承父类的所有公共和受保护属性及方法。

  • 组合 (Composition) - "has-a" 关系: 当一个类包含另一个类的实例作为其属性时,使用组合。例如,Car has an Engine(汽车有一个引擎)。这表示一个对象由其他对象组成。

原代码问题分析: 原始代码中,Clinic类继承了Patient类:class Clinic extends Patient。 从业务逻辑上看,一个诊所(Clinic)并不是一个患者(Patient)。诊所应该拥有管理患者,而不是一个患者。这种“is-a”关系的错误应用导致了类设计的混淆。Clinic类中定义了$patients数组来存储Patient对象,这本身就表明了Clinic与Patient之间是“has-a”的关系。

解决方案:移除不当的继承Clinic类不应继承Patient类。它应该通过组合的方式,在其内部维护一个Patient对象的集合。

patients;
    }

    public function assignPatient($name, $age, $gender){
        // 通过组合,Clinic内部创建并管理Patient对象
        $this->patients[] = new Patient($name, $age, $gender); 
    }

    public function deletePatient($index){
        unset($this->patients[$index]);
        // 重新索引数组以避免空洞,可选但推荐
        $this->patients = array_values($this->patients); 
    }
}

3. 完整修正后的代码示例

结合上述两点修正,以下是优化后的PHP代码:

name = $name;
        $this->age = $age;
        $this->gender = $gender;
    }   

    public function getName(){
        return $this->name;
    }

    public function getAge(){
        return $this->age;
    }

    public function getGender(){
        return $this->gender;
    }
}

class Clinic {
    private $patients = [];

    public function getPatients(){
        return $this->patients;
    }

    public function assignPatient($name, $age, $gender){
        $this->patients[] = new Patient($name, $age, $gender);
    }

    public function deletePatient($index){
        unset($this->patients[$index]);
        // 重新索引数组以确保连续性,避免后续操作出现意外
        $this->patients = array_values($this->patients);
    }
}

// 实例化并测试
$clinic = new Clinic();

$clinic->assignPatient("Patrick star",18,"Male");
$clinic->assignPatient("SpongeBob Squarepants",17,"Male");
$clinic->assignPatient("Eugene Krab",28,"Male");

$clinic->deletePatient(1); // 删除索引为1的患者 ("SpongeBob Squarepants")

print_r($clinic->getPatients());
?>

代码输出:

Array
(
    [0] => Patient Object
        (
            [name:Patient:private] => Patrick star
            [age:Patient:private] => 18
            [gender:Patient:private] => Male
        )

    [1] => Patient Object
        (
            [name:Patient:private] => Eugene Krab
            [age:Patient:private] => 28
            [gender:Patient:private] => Male
        )

)

从输出可以看出,Patient对象的属性已正确初始化,并且Clinic对象现在正确地管理着一个Patient对象的集合。deletePatient操作后,数组也进行了重新索引。

4. 注意事项与最佳实践

  • 明确构造函数的作用: 始终将__construct方法用于初始化对象的基本状态。如果对象创建时需要参数,确保__construct能够接收并处理这些参数。
  • 选择合适的类关系: 在设计类时,仔细思考它们之间的关系是“is-a”(继承)还是“has-a”(组合)。错误的类关系会导致不必要的复杂性、难以维护的代码以及潜在的逻辑错误。通常,组合比继承更灵活,更推荐使用。
  • 私有属性的访问: 属性声明为private后,只能在类的内部访问。如果需要在外部获取这些属性值,必须提供公共的getter方法(如getName())。
  • 数组操作后的重新索引: 当从数组中unset元素后,数组的键可能不再连续。如果后续操作依赖于连续的数字索引,应使用array_values()等函数进行重新索引,如$this->patients = array_values($this->patients);。

通过遵循这些原则,可以有效避免在PHP面向对象编程中常见的NULL值输出问题,并构建出更加清晰、健壮和易于维护的应用程序。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
c语言中null和NULL的区别
c语言中null和NULL的区别

c语言中null和NULL的区别是:null是C语言中的一个宏定义,通常用来表示一个空指针,可以用于初始化指针变量,或者在条件语句中判断指针是否为空;NULL是C语言中的一个预定义常量,通常用来表示一个空值,用于表示一个空的指针、空的指针数组或者空的结构体指针。

237

2023.09.22

java中null的用法
java中null的用法

在Java中,null表示一个引用类型的变量不指向任何对象。可以将null赋值给任何引用类型的变量,包括类、接口、数组、字符串等。想了解更多null的相关内容,可以阅读本专题下面的文章。

458

2024.03.01

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

52

2025.11.27

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

52

2025.11.27

go语言 面向对象
go语言 面向对象

本专题整合了go语言面向对象相关内容,阅读专题下面的文章了解更多详细内容。

56

2025.09.05

java面向对象
java面向对象

本专题整合了java面向对象相关内容,阅读专题下面的文章了解更多详细内容。

52

2025.11.27

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

14

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
PHP课程
PHP课程

共137课时 | 10.3万人学习

JavaScript ES5基础线上课程教学
JavaScript ES5基础线上课程教学

共6课时 | 11.2万人学习

PHP新手语法线上课程教学
PHP新手语法线上课程教学

共13课时 | 0.9万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号