PHP10:面向对象

思想图解:
就是把个个方法对应到它的主题,买家的方法就对应到买家那里,卖家的方法就放到卖家那里,凡是做任何一件事都有一个操作的主体,虽然更复杂,但是更符合人类的思想
在这里插入图片描述
在这里插入图片描述

关键字说明

  • 类: class,是定义面向对象主体的最外层结构,用来包裹主体的数据和功能(函数)。类是一类具有共性事务的代表,代表的是事务的共性。
  • 对象: object,是某类事务的具体代表,也是实际数据和功能操作的具体单元,也被称之为实例(instance)
  • 实例化: new,从一个抽象的概念得到一个符合抽象概念的具体实例的过程
  • 类成员:member,指类class结构中的所有内容,类成员里有三种
    • 方法: method,本质是在类class结构中创建的函数,也称之为成员方法或者成员函数
    • 属性: property,本质是在类class结构中创建的变量,也称之为成员变量
    • 类常量: const,本质是在类class结构中创建的常量

类的定义

在这里插入图片描述

类成员

类成员:指直接定义在类结构内部的一级成员,即直接依赖f的成员

  • 类成员分类

    • 成员变量(属性)︰给对象存储数据的变量。成员函数((方法)︰给对象调用解决问题的函数
    • 类常量:属于类内部的常量,使用const关键字定义
  • 属性和方法需要使用访问修饰限定符修饰,姑且使用public修饰

<?php
    class 类名{
        # 类常量
        const 常量名 =;
        # 属性
        public $属性名 [ =]; # 可以赋值也可以只声明
        # 方法
        [public] function 方法名([形参列表]){
            方法体
        }
    }
  • 成员访问:属性和方法都属于对象访问,类常量属于类访问(后续再讲)
    • 对象访问属性和方法,使用->
<?php
    # 实例化
    $object = new 类名();
    # 属性访问
    # 此时不带属性本身的$符号(前面保存对象的变量带$符号,object->属性名是整体)
    $object -> 属性名;
    # 方法访问
    $object -> 方法名([实参列表]);

步骤
1、声明类结构工
2、明确类产生的对象是否需要有数据的存储:确定属性
3、明确类产生的对象是否需要函数实现功能:确定方法
4、明确类是否需要定义常量:确定类常量
5、对象实例化
6、类成员访问(属性和方法)

实例:
在这里插入图片描述
属性的操作:
增,删,改,查
在这里插入图片描述
在这里插入图片描述

小结

1、PHP类结构中有且仅有三种成员:属性、方法和类常量,其他直接属于类的内容都会报错
2、类声明需要根据业务来确定类成员的存在和数量
3、类中属性和方法的访问方式都是通过对象来调用: $对象->属性名/方法名();注意属性名不带$符号
4、类中定义属性不能直接属性名,需要使用符号public修饰(访问修饰限定符中的一种)

访问修饰限定符

分类:

  • public:公有,类内和类外都可以访问
  • protected:受保护,只允许在相关类内部访问(前期的学习就当作私有)
  • private:私有,只允许在定义类内部访问
  • 属性必须有访问修饰限定符,方法可以没有访问修饰限定符(默认public)

类内部对象

概念

内部对象:$this,方法内部内置的一个对象,会自动指向来调用方法的对象

  • $this存在于方法内部(仅限内部使用),所以相当于在类的结构内部
    • 可以访问任意访问修饰限定符修饰的成员
    • 私有成员都是通过公有方法来实现访问(公有方法可以在类外部访问)
  • 类内部对类成员的访问也需要通过对象才能访问,所以必须通过$this内部对象访问类成员

步骤

  • 声明类结构

  • 明确私有成员(不限定成员的访问修饰限定符)

  • 私有成员需要在某种情况下被访问:增加方法,在方法里使用$this访问

例如:在类内部访问属性,可以让本来不能访问类的私有的属性和方法的对象成功访问

class Saler{
  	# 属性
  	public $count = 100;
  	protected $discount = 0.8;
  	private $money = 100;
    
    public function getAll(){
        var_dump($this);
        echo $this->count,$this->discount,$this->money;		#正确输出
    }					
}

$s = new Saler();
$s->getAll();

$this、class和new之间的关系原理

  • class是定义类结构,属于非执行段代码,因此会被加载到代码段(编译阶段)

  • new是实例化对象,先判定类在内存(代码段)是否存在

    • 类不存在,报错;
    • 类存在,将类内部的属性部分复制一份,然后在内存(堆区)开辟一块内存空间,将属性放到里面,同时内部有一个指针指向类的内存空间(代码段)
    • 对象访问属性即访问的是对象空间里存储的部分
    • 对象访问方法是对象通过内部指针找到类空间中的方法,然后在内存(栈区)开辟运行
  • $this是系统在方法内置的对象通用名字

    • 对象在调用方法的时候,系统会自动找到对象所保存的内存地址(堆区),然后把地址赋值给$this
  • 方法内部的$this就代表调用当前$this所在方法的外部对象

    • $this的本质是函数内部的一个局部变量,只是系统自动对其进行赋值,而且一定是调用方法的对象本身
  • 面向对象编程代码运行内存关系

构造方法

概念

构造方法__construct(),是一种类结构特有的特殊方法,该方法由系统规定好,开发人员在定义的时候只需要一遍,有了构造方法的类在实例化对象之后,对象就会自动调用。

  • 构造方法是一种魔术方法:魔术方法是会自动被触发,不需要手动调用的方法
  • 构造方法的目标是为了实现对象的初始化
    • 对象实例化之后会自动调用
    • 构造方法通常是为了实现对象所需资源的初始化(属性、资源)
  • 构造方法虽然为魔术方法,但本质依然是一个方法
    • 受访问修饰限定符控制(对象的产生位置会发生改变)
    • 对象可以选择调用(一般不会)
  • 构造方法可以设定形参,形参对应的实参是在实例化对象的时候传入:new 类名(实参传递给形参)

步骤

  • 确定类中需要有数据实现初始化,而且是灵活处理,每个对象都不一样的:使用构造方法

  • 确定初始化的数据需要外部传入:使用构造方法设定形参

  • 在构造方法内部利用内部对象实现初始化需求

    • 属性初始化
    • 资源初始化
    • 其他内置方法调用
  • 实例化对象时必须传入构造方法所需数据

示例

1、构造方法实现:在类中增加一个方法__construct()即可

2、构造方法也是一个方法,不普通的地方在于,类实例化得到的对象会马上自动调用

3、一旦构造方法拥有了形参,那么对象在调用该方法的时候就需要传入对应的实参,而构造方法又是自动调用的,所以需要在实例化对象的时候使用new 类名(构造方法对应的实参列表)来实现

4、构造方法不管再怎么特殊,也是用户定义的方法,言外之意除了在实例化对象时对象会自动调用之外,我们也可以手动调用构造方法(但是一般没有价值,因为对象实例化时会自动调用)

class Saler{
  	# 属性
  	public $count;				
  	private $money;
    
    # 构造方法:初始化属性
    public function __construct($count,$money){
        $this->count = $count;
        $this->money = $money;
    }
}

# 实例化
$s = new Saler(100,100);			# 系统在new Saler(100,100)好之后,会自动调用一次
$s->__construct(1000,1000);			# 允许手动调用

小结

1、构造方法__construct()是一种系统内置的方法,该方法的特性是会在对象实例化之后,对象立即自动调用

2、构造方法的目的就是为了初始化资源,包含对象属性和其他资源

3、一旦构造方法定义好之后,且构造方法自带参数,那么就只能使用new 类名(参数列表)方式才能正确实例化

4、构造方法可以当做普通方法由对象调用(不建议)

析构方法

概念

析构方法__destruct(),也是一种类结构中魔术方法,与构造方法一样,也是系统规定好,只需要开发人员一遍即可,对象在被销毁时会自动调用

  • 析构方法是用来对象销毁时主动释放资源的
  • 对象销毁的方式:
    • 对象无变量指向(变量指向其他数据比如重新赋值)
    • 对象被主动销毁(unset销毁对象变量)
    • 脚本执行结束(自动释放资源)
  • PHP脚本执行结束会释放所有资源,所以一般较少使用析构方法

步骤

1、定义类结构

2、确定需要在对象销毁时释放资源

3、使用析构方法释放资源

示例

1、析构方法实现:类中增加一个__destruct()方法

class Saler{
  	# 析构方法
    public function __destruct(){
        echo __FUNCTION__;
    }
}

2、析构方法调用:析构方法是在对象被销毁时自动,对象的“垂死挣扎”

# 实例化对象
$s = new Saler();

# 对象变量指向其他数据
$s = 1;	

# 主动销毁对象变量
unset($s);			

# 脚本执行结束自动释放

3、析构方法也是普通方法,可以由对象直接调用

# 接析构方法实现代码
$s = new Saler();
$s->__destruct();		# 调用了对象是不会被销毁的

小结

1、析构方法是一种对象销毁时自动调用的方法

2、析构方法是用来对象销毁自身所占用的资源

3、PHP中脚本执行结束,系统会自动回收所有资源,因此一般PHP中很少使用析构方法

对象传值

概念

对象传值:将保存对象的变量赋值给另外一个变量

  • 在PHP中,对象的传值是引用传递的:即一个对象变量赋值给另外一个变量,两个变量指向同一个对象的内存地址,即只有一个对象。

步骤

1、定义类结构

2、实例化产生对象,保存在变量中

3、将保存对象的变量赋值给另外一个变量

示例

  • 对象传值就是保存对象的变量赋值给另外一个变量

  • 对象传值是引用传递,不管对象赋值给多少个变量,内存中只有一个对象

class Saler{}
$s1 = new Saler();
$s2 = $s1;
var_dump($s1,$s2);		# 同一个对象
$s1->name = 'Saler';	# 更改一个变量所保存对象的属性
echo $s2->name;			# 输出Saler

小结

对象传值方式是引用传值,不论对象如何被赋值给其他变量,始终只有一个对象

范围解析操作符(类常量访问)

概念

范围解析操作符:由两个冒号组成“::”,是专门用于类实现类成员操作的(区别于对象对类成员操作),可以实现类直接访问类成员

  • 范围解析操作符是用于给类(类名)访问类成员使用的
类名::类成员
  • 范围解析操作符也可以被对象用来当做类使用(不建议使用)
$对象名::类成员
  • 类常量只能被类访问

步骤

1、定义类结构

2、确定成员需要由类进行管理:类常量

3、在需要访问类常量的时候使用范围解析操作符访问

示例

1、类常量的普通访问尝试:尝试使用对象进行访问

class Saler{
	# 类常量
    const PI = 3.14;
}
$s1 = new Saler();
echo $s1->PI;			# 错误,$s1->PI最终转换的访问方式为:$PI,这个在类中并不存在

2、以上案例可以看出,对象无法访问类常量,那是因为类常量的定义本身就是用来给类访问的,对象是用来访问属性和方法的,类常量的访问方式为:类名::常量名,而且类的访问不需要依靠对象,就算没有实例化对象也可以访问

# 类+范围解析操作符访问类常量
echo Saler::PI;			# 输出3.14

3、对象本身也依赖于类,因此也可以使用对象对类控制成员进行访问,需要使用范围解析操作符

$s = new Saler();
echo $s::PI;			# 输出3.14

注意:以上方式能访问,但是不建议使用(以上方式也能看出,成员谁来访问,关键看用什么符号:①使用范围解析操作符::就是类访问;②使用对象操作符号->就是对象访问)

4、分析:类常量是固定的,而对象的属性是不同对象而不同的,成员方法简单的理解也是为属性本身进行加工的。因此有一些东西是专属于类的,而有部分内容是专门为对象提供的,所以就会有不同的成员拥有不同的访问方式

小结

1、类访问成员的方式是使用范围解析操作符“::”访问,由类名直接访问:类名::类常量

2、类本身是通过对同类对象的抽象而形成,所以属性和方法本身都是由对象来访问

3、类也需要有一些自身的数据和操作,这些就由类来进行访问

静态成员

概念

静态成员:使用static关键字修饰的类成员,表示该成员属于类访问(专用于类)

  • PHP静态成员有两种
    • 静态属性
    • 静态方法
  • 静态成员是明确用来给类访问的,而不是对象
  • 静态成员只是多了一个static关键字修饰,本身也可以被对象访问
  • 静态成员同样可以使用不同访问修饰限定符限定,效果一致

步骤

1、定义类结构

2、确定有些成员(属性、方法)不需要对象访问,直接通过类访问

3、使用static关键字修饰

4、静态成员应该让类进行访问

示例

1、静态属性:在类中定义属性的时候使用static关键字修饰,访问的时候只能使用类+范围解析操作符+静态属性访问,对象不能访问静态属性

class Saler{
	# 属性
    public $money = 0;
    public static $count = 0;	# 静态属性
}

# 静态成员可以直接使用类访问,而不需要先实例化对象
echo Saler::$count;
$s = new Saler;
echo $s->count; # 错误访问,对象不能访问静态属性

2、静态方法:在类中定义方法的时候使用static关键字修饰,访问的时候使用类+范围解析操作符+静态方法名字()访问

class Saler{
	# 方法
    public static function showClass(){
        echo __CLASS__;
    }
}

# 类直接访问
Saler::showClass();

3、在类的内部也可以访问静态成员,同样是使用类名+范围解析操作符+静态属性/静态方法()

class Saler{
    # 属性
    private static $count = 0;	# 私有,不允许外部直接访问
	# 方法
    public static function showClass(){
        echo Saler::$count;
    }
}

# 类直接访问
Saler::showClass();

4、静态方法本质也是类中定义的方法,因此也可以使用对象进行访问,但是不建议

# 对象访问静态方法
$s = new Saler();
$s->showClass();	# 输出0

5、同理,方法也是在类内部,在编译时就存在,因此可以通过类来进行访问,使用范围解析操作符,但是非常不建议(会报错:因为类只允许访问静态成员和类常量)

class Saler{
    public function testStatic(){
        echo __FUNCTION__;
    }
}

# 类访问普通成员方法
Saler::testStatic();	# 输出testStatic,但是报错,当前访问的不是静态方法

6、静态方法本质是给类访问,所以不允许在静态方法内部使用$this对象

class Saler{
    public static function testStaticThis(){
        var_dump($this);	# 致命错误:$this放到了不该放的位置
    }
}			

小结

1、为了保障类能直接访问数据和操作数据,可以在属性和方法前增加static关键字变成静态属性和静态方法

2、类通过类名+范围解析操作符+静态成员的方式进行访问

3、静态成员也受访问修饰限定符的限定,访问权限与普通属性和方法的限制一样

4、对象可以无条件访问静态方法,而类只能访问不带$this的普通方法(不建议)

5、静态成员是给类访问的,非静态成员是给对象访问的

  • 静态属性和方法(静态和非静态)都是保存在类结构中(代码段)
  • 普通属性保存在对象生成的对象空间里(堆)

6、静态成员的访问效率比非静态成员高,因此有种说法是能用静态的时候就不用非静态(对象的特点是多元化,而静态的特点是单一化)

self关键字

概念

self关键字:在类的内部(方法里面)使用,代替类名的写法

  • self如同$this代表内部对象一样,能够在方法内部代替当前类名

  • 能够保障用户方便修改类名字

  • self关键字是代替类名,所以需要配合范围解析操作符::

步骤

1、定义类结构

2、方法内部需要使用类名来进行成员访问(类常量、静态成员)

3、使用self关键字代替类名

示例

1、self是用来代替类名的,与范围解析操作符::一起使用的

class Saler{
    # 静态属性
    private static $count = 0;			# 私有,不允许外部直接访问
	# 静态方法
    public static function showClass(){
        echo Saler::$count;
        echo self::$count;				# 代替类名
    }
}

2、self也可以在类的内部方便实例化对象:比如构造方法被私有化之后,就没有办法在类外部实例化对象,此时可以在类内部进行对象实例化

class Saler{
    # 属性
    private static $count = 0;			# 私有,不允许外部直接访问
    private function __construct(){}	# 私有,不允许外部实例化(因为对象不能外部调用)
	# 方法
    public static function getInstance(){
        return new Saler();		# 使用类名实例化
        return new self();		# 使用self关键字实例化
    }
}

$s = Saler::getInstance();

小结

1、self是一种在类内部用来代替类名的关键字

2、self可以用来在类内部访问静态成员

3、self也可以在类内部用来实例化对象

4、帮助类名修改时,不用修改任何类的内部结构

  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

huamanggg

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值