PHP面向对象编程

PHP面向对象编程

PHP面向对象编程(简称OOP)是一种编程范式,通过使用类、对象、继承、封装、多态等概念来组织和管理代码。PHP从版本5开始引入了全面的面向对象支持,并提供了丰富的面向对象编程特性。

PHP面向对象编程的特点(或者说OOP基本都具有得特点):

  1. 类:类是面向对象编程的基本构建块,用于定义对象的属性(成员变量)和行为(方法)。类可以看作是对象的蓝图或模板。

  2. 对象:对象是类的实例化,具体的实体。对象具有类定义的属性和方法,并可以通过对象访问和操作它们。

  3. 封装:封装是一种将数据和相关操作封装在类中的机制,通过访问控制(public、private、protected)来控制对类的成员的访问。

  4. 继承:继承允许一个类(子类)继承另一个类(父类)的属性和方法。子类可以扩展或重写父类的功能,实现代码的复用和层次化结构。

  5. 多态:多态允许使用统一的接口来处理不同类的对象。通过继承和接口实现,可以在不同的类中使用相同的方法名称,但具体的实现可能不同。

  6. 抽象类:抽象类是一种不能被实例化的类,用于作为其他类的基类。它可以定义抽象方法和具体方法,子类必须实现抽象方法。

  7. 接口:接口定义了一组方法的规范,但不包含具体实现。类可以实现一个或多个接口,实现接口的类必须实现接口中定义的所有方法。

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 CLI模式下输出得结果:
请添加图片描述

类的继承

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 关键字,并且不需要提供具体的实现。子类继承抽象类后,必须实现父类中的所有抽象方法,否则子类也必须声明为抽象类。

<?php

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 声明的成员变量为静态变量或叫类变量,是该类的公共变量,在第一次使用时即生成,对于该类的所有对象只有一份,是属于类的,不是属于对象的。static 变量是属于类而不属于对象,可以在任何地方通地类来访问,是类的全局变量,类创建时即存入内存。对多个对象来说,静态数据成员只存储一处,可以节省内存。只要对静态数据成员的值更新一次,保证所有对象存取更新后的相同的值。

static 方法:

  • 用 static 声明的方法为静态方法或叫类方法,执行该方法时不会将对象引用传给函数,所以我们不能访问非静态成员,只能访问静态方法或静态变量。只能使用关于类的方式如 self static parent 等。使用时不用生成对象即可执行

类常量:

使用 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', 'john@example.com');
echo $user->name; // 输出:John Doe
echo $user->email; // 输出:john@example.com

$user->age = 25;
echo $user->age; // 输出:25

echo $user; // 输出:User: John Doe (john@example.com)

$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
  • 38
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

代码炼金术

何以解忧,唯有打赏!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值