
在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,使其成为真正的构造函数。
<?php
class Patient{
private $name;
private $age;
private $gender;
public function __construct($name, $age, $gender){ // 正确的构造函数
$this->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免费学习笔记(深入)”;
面向对象设计中的两个核心概念是继承和组合。正确选择它们对于构建健壮、可维护的代码至关重要。
继承 (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对象的集合。
<?php
// ... Patient class (as corrected above) ...
class Clinic { // 不再继承Patient
private $patients = []; // Clinic 拥有一个患者列表
public function getPatients(){
return $this->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);
}
}结合上述两点修正,以下是优化后的PHP代码:
<?php
class Patient{
private $name;
private $age;
private $gender;
public function __construct($name, $age, $gender){
$this->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操作后,数组也进行了重新索引。
通过遵循这些原则,可以有效避免在PHP面向对象编程中常见的NULL值输出问题,并构建出更加清晰、健壮和易于维护的应用程序。
PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号