PHP面向对象编程(简称OOP)是一种编程范式,通过使用类、对象、继承、封装、多态等概念来组织和管理代码。PHP从版本5开始引入了全面的面向对象支持,并提供了丰富的面向对象编程特性。
PHP面向对象编程的特点(或者说OOP基本都具有得特点):
类:类是面向对象编程的基本构建块,用于定义对象的属性(成员变量)和行为(方法)。类可以看作是对象的蓝图或模板。
对象:对象是类的实例化,具体的实体。对象具有类定义的属性和方法,并可以通过对象访问和操作它们。
封装:封装是一种将数据和相关操作封装在类中的机制,通过访问控制(public、private、protected)来控制对类的成员的访问。
继承:继承允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以扩展或重写父类的功能,实现代码的复用和层次化结构。
多态:多态允许使用统一的接口来处理不同类的对象。通过继承和接口实现,可以在不同的类中使用相同的方法名称,但具体的实现可能不同。
抽象类:抽象类是一种不能被实例化的类,用于作为其他类的基类。它可以定义抽象方法和具体方法,子类必须实现抽象方法。
接口:接口定义了一组方法的规范,但不包含具体实现。类可以实现一个或多个接口,实现接口的类必须实现接口中定义的所有方法。
PHP面向对象编程提供了更模块化、可维护和可扩展的代码结构。它可以帮助开发者组织和管理复杂的应用程序,并提供了更高的代码重用性和灵活性。
除了面向对象编程还有面向过程:
程序员设计好程序代码流程图,辅助程序设计。优点:用什么功能就编写什么函数 缺点:数据管理上比较混乱 ,主要集中在函数成面上,面向对象把属性和方法进行封装,更好的可重用性和可扩展性。
面向过程的编程语言有:C语言、Fortran、Pascal(也可以OOP)、COBOL
类与对象
万物皆对象,将构成问题的事务分解到各个对象上,建立对象的目的不是为了完成一个工作,而是为了描述某个事务在解决问题中的行为,更符合人的思维习惯,代码重用性高,可扩展性好。面向对象是由一系统具有属性和方法的对象构成,对象之间相互交互 ,从而实现业务需求。
简单理解:先要有类,然后生成对象,对象有属性和方法。
属性:在类中定义的变量,即为成员属性,用于描述对象静态特性的数据可以通过对象来访问和修改。
方法:函数定义在类中即为成员方法,用于描述对象动态特性的操作行为。
生命周期:创建后,生命周期开始,当程序结束后或程序员清除对象后即销毁,或者PHP自动销毁对象。
命名规范:首字母大写,一般一个类放一个文件中。
class Person{
public string $name = '啊小';
public int $age = 18;
public string $sex = '女';
public function say():void
{
//说话的方法
}
public function run():void
{
//奔跑的方法
}
}
$anoxia = new Person; // $xiaoxiao 就是一个对象,通过关键字 new 生成。
echo $anoxia->name; //以下是访问属性和方法的调用方式
echo $anoxia->age;
echo $anoxia->sex;
$anoxia->say();
$anoxia->run();
** t h i s ∗ ∗ : 对象中使用 ‘ this**: 对象中使用 ` this∗∗:对象中使用‘this` 指针可以访问属性或方法。
class Person {
public string $name = '啊小';
public int $age = 18;
public string $sex = '女';
public function say(): void {
echo "{$this->name}说:我性别是{$this->sex}的,今年{$this->age}岁了";
}
public function run(): void {
echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
}
}
$anoxia = new Person();
echo $anoxia->name . PHP_EOL;
echo $anoxia->age . PHP_EOL;
echo $anoxia->sex . PHP_EOL;
$anoxia->say();
$anoxia->run();
注意: PHP_EOL 是预定义常量,它表示换行符(line break)。
不同操作系统使用不同的换行符来表示新行。例如,Windows 系统使用回车符和换行符(“\r\n”),Unix/Linux 系统使用换行符(“\n”),Macintosh 系统使用回车符(“\r”)。
类的继承
php通过使用 extends
可以继承父类的属性与方法,在 PHP 中继承是单一的。(多继承可以通过Trait)
class Person {
public string $name = '迪迦';
public int $age = 1000;
public string $sex = '难';
public function say(): void {
echo "{$this->name}说:我是{$this->sex}的,今年{$this->age}岁了";
}
public function run(): void {
echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
}
}
class SupperMan extends Person {
public int $ap = 99;
public int $mp = 100
public string $special_move = "动感光波";
public function attacks():void
{
echo "超人:{$this->name},攻击力:{$this->ap},能量值:{$this->mp},必杀技:{$this->special_move}";
}
}
$supperMan = new SupperMan();
$supperMan->say();
echo PHP_EOL;
$supperMan->run();
echo PHP_EOL;
$supperMan->attacks();
子类调用父类、方式重写、禁止重写
class Person {
public string $name = '迪迦';
public int $age = 1000;
public string $sex = '难';
public function say(): void {
echo "{$this->name}说:我是{$this->sex}的,今年{$this->age}岁了";
}
public function run(): void {
echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
}
// public final function run(): void {
// echo "{$this->name}说:今年{$this->age}岁,我可以跑得很快";
// }
}
class SupperMan extends Person {
public int $ap = 99;
public int $mp = 100;
public string $special_move = "动感光波";
public function attacks():void
{
echo "超人:{$this->name},攻击力:{$this->ap},能量值:{$this->mp},必杀技:{$this->special_move}";
}
public function fly():void{
echo "超人:{$this->name},除了再地面对战还可以飞";
}
public function run(): void
{
parent::run(); // 直接用parent::方法名 调用父类的方法
echo "超人:{$this->name},特有的跑步姿势!帅";
}
}
$supperMan = new SupperMan();
$supperMan->run();
echo PHP_EOL;
注意:当子类与父类方法名一致时即方法重写,如果想调用父类可以用直接用parent::方法名 调用父类的方法,当父类方法使用了final声明,那么子类就不能重写父类方法。
封装
名称 | 介绍 |
---|---|
public 公有 | 在类的内部与外部或子类都可以访问,是最开放的权限 |
private 私有 | 定义类的属性和方法,在类的内部可以访问,在类的外部或子类都不可以访问 |
protected 受保护 | 定义类的属性和方法,在类的内部或子类可以访问,类的外部不可以访问 |
多继承(Trait)
Trait 是一种代码复用机制,它允许开发者在不同类之间共享方法的集合。当使用多个 Trait 时,可以通过逗号分隔的方式在类中引入多个 Trait。可能会遇到方法命名冲突或访问控制的问题,可以使用 insteadof
关键字来明确指定使用哪个 Trait 中的方法。
trait TraitA {
public function foo() {
echo "TraitA's foo\n";
}
}
trait TraitB {
protected function foo```php
trait TraitA {
public function foo() {
echo "TraitA's foo\n";
}
}
trait TraitB {
protected function foo() {
echo "TraitB's foo\n";
}
}
trait TraitC {
protected function foo() {
echo "TraitC's foo\n";
}
}
class MyClass {
use TraitA, TraitB, TraitC {
TraitC::foo as public bar; // 将TraitC的foo方法重命名为bar,并设置为public访问权限
TraitB::foo insteadof TraitA, TraitC; // 解决TraitA、TraitC和TraitB之间的冲突
}
}
$obj = new MyClass();
$obj->foo(); // 输出:TraitB's foo
$obj->bar(); // 输出:TraitC's foo
抽象方法
抽象方法是一种在抽象类中声明但不提供具体实现的方法。抽象方法只能存在于抽象类中,而抽象类本身不能被实例化,只能被继承。
要声明一个抽象方法,需要在方法前面加上 abstract
关键字,并且不需要提供具体的实现。子类继承抽象类后,必须实现父类中的所有抽象方法,否则子类也必须声明为抽象类。
abstract class Animal {
abstract public function makeSound();
}
class Dog extends Animal {
public function makeSound() {
echo "Woof!\n";
}
}
class Cat extends Animal {
public function makeSound() {
echo "Miao!\n";
}
}
$dog = new Dog();
$dog->makeSound(); // 输出:Woof!
$cat = new Cat();
$cat->makeSound(); // 输出:Miao!
静态方法
在PHP中,静态方法是属于类本身而不是类的实例的方法。可以通过类名直接调用静态方法,而无需创建类的实例。
要声明一个静态方法,需要在方法前面加上 static
关键字。静态方法可以直接访问类的静态属性,并且不能访问非静态属性。
class MathUtils {
public static function sum(int $a, int $b):int
{
return $a + $b;
}
public static function multiply(int $a, int $b):int
{
return $a * $b;
}
public function sub(int $a, int $b):int
{
return self::multiply($a, $b) - self::sum($a,$b);
}
}
// 调用静态方法
echo MathUtils::sum(5, 3); // 输出:8
echo MathUtils::multiply(5, 3); // 输出:15
$m = new MathUtils();
echo($m->sub(5, 3)); //输出:7
static
static 变量:
static 方法:
类常量:
使用 const
来定义类常量,常量使用 self::
来调用。
类的魔术方法
PHP中的魔术方法(Magic Methods)是一组特殊的方法,用于在特定的情况下自动调用。这些方法以两个下划线(__)开头和结尾,它们允许您拦截并响应类的内部事件,例如实例化、属性访问、方法调用等。
方法名 | 备注 |
---|---|
__construct() | 当一个对象被实例化时自动调用的构造方法。 |
__destruct() | 当一个对象不再被引用时自动调用的析构方法。 |
__get($property) | 在访问一个不存在或不可访问的属性时自动调用,可以用于动态获取属性的值。 |
__set($property ,$value ) |
在给一个不存在或不可访问的属性赋值时自动调用,可以用于动态设置属性的值。 |
__isset($property) | 在使用 isset() 或 empty() 检查一个不存在或不可访问的属性时自动调用。 |
__call($method, $arguments ) |
在调用一个不存在或不可访问的方法时自动调用。 |
__callStatic($method , $arguments ) |
在调用一个不存在或不可访问的静态方法时自动调用。 |
__unset($property) | 在使用 unset() 删除一个不存在或不可访问的属性时自动调用。 |
__sleep() | 在使用 serialize() 时自动调用,用于准备对象序列化过程中需要保存的属性列表。 |
__wakeup() | 在使用 unserialize() 时自动调用,用于重新初始化对象。 |
__toString() | 当将对象作为字符串进行输出时自动调用。 |
__set_state($data) | 在使用 var_export() 导出类时自动调用,用于返回类的代码表示。 |
__clone() | 当通过 clone 关键字克隆一个对象时自动调用。 |
__debugInfo() | 在使用 var_dump() 或 print_r() 打印对象时自动调用,用于返回调试信息的数组。 |
class User {
private $data = [];
public function __construct($name, $email) {
$this->data['name'] = $name;
$this->data['email'] = $email;
}
public function __get($property) {
if (isset($this->data[$property])) {
return $this->data[$property];
}
return null;
}
public function __set($property, $value) {
$this->data[$property] = $value;
}
public function __toString() {
return "User: " . $this->data['name'] . " (" . $this->data['email'] . ")";
}
public function __call($method, $arguments) {
if ($method === 'greet') {
$name = isset($arguments[0]) ? $arguments[0] : 'Guest';
echo "Hello, $name! Nice to meet you!";
}
}
}
$user = new User('John Doe', '[email protected]');
echo $user->name; // 输出:John Doe
echo $user->email; // 输出:[email protected]
$user->age = 25;
echo $user->age; // 输出:25
echo $user; // 输出:User: John Doe ([email protected])
$user->greet('Alice'); // 输出:Hello, Alice! Nice to meet you!
抽象类与抽象方法
抽象类和抽象方法是面向对象编程中的概念,用于实现抽象和多态性的特性。具有抽象方法的类为抽象类,抽象方法即为没有内容的空方法,要求子类进行完善内容,抽象类不能实例化,只能继承,通过 extends 来实现,抽象类中也可以定义普通方法。
注意:
抽象类(Abstract Class)是不能被实例化的类,它只能被用作其他类的基类。抽象类可以包含具体的方法实现,也可以包含抽象方法的声明。抽象类通过 abstract
关键字进行声明。
抽象方法(Abstract Method)是在抽象类中声明的方法,没有具体的实现代码。它只是定义了方法的名称、参数列表和返回类型,而具体的方法实现需要在继承的子类中完成。抽象方法通过在方法声明中使用 abstract
关键字进行声明。
abstract class AbstractClass
{
// 强制要求子类定义这些方法
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// 普通方法(非抽象方法)
public function printOut() {
print $this->getValue();
}
}
接口(interface )
接口(Interface)是一种定义了一组方法的抽象类型,它只定义了方法的签名(名称、参数和返回类型),而没有具体的实现。接口可以被类实现(implement),一个类可以实现一个或多个接口。
接口与抽象类的区别:
1 接口只能用 implements 实现 抽象类用 extends 继承实现。
2 接口没有数据成员,可以定义常量,抽象类可以有。
3 接口没有构造函数,抽象类可以定义构造函数。
4 接口方法都是 public 抽象类方法可以用 protected private public 来修饰。
5 一个类可以实现多个接口,但只能继承一个抽象类。
6 接口中不可以有成员方法,抽象类可以有成员方法。
例子:
interface Logger {
public function log($message);
}
class DbOperate implements Logger {
public function log($message) {
echo "Logging message to a file: $message\n"; //实现log接口方法
}
}
class CreateGoods implements Logger {
public function log($message) {
echo "Logging message to a createGoods: $message\n"; //实现log接口方法
}
}
$fileLogger = new DbOperate();
$fileLogger->log("Error Info"); // 输出:Logging message to a file: Error Info
$databaseLogger = new CreateGoods();
$databaseLogger->log("Warning"); // 输出:Logging message to a createGoods: Warning