类内部对象|学习笔记

简介: 快速学习类内部对象

开发者学堂课程【PHP 进阶教程-由浅入深掌握面向对象开发-第一阶段类内部对象】学习笔记,与课程紧密联系,让用户快速学习知识。  

课程地址:https://developer.aliyun.com/learning/course/711/detail/12661


类内部对象

 

类内部对象

1、目标

理解内部对象的概念,掌握内部对象对成员的访问

公有和私有的属性或者方法叫做访问修饰限定符限定访问的区间。

2、概念

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

(1)$this 存在于方法内部(仅限内部使用),所以相当于在类的结构内部

可以访问任意访问修饰限定符修饰的成员

私有成员都是通过公有方法来实现访问(公有方法可以在类外部访问)(因为如果方法私有化,外边还不能调用方法,方法自然就无法实现里面的代码去运行)

(2)类内部对类成员的访问也需要通过对象才能访问,所以必须通过$this 内部对象访问类成员(函数里面必须通过对象才能访问对象里面的成员)

3、步骤

(1)声明类结构

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

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

4、示例

(1)尝试在类内部方法中访问属性

class saler{

# 属性

public $count = 100;

protected $discount = 0.8;

private $money=100;

public function geta11(){

echo $count,$discount,$money;;# 全部错误:提示未定义的“变量”

}

}

$s=new saler();

$s->geta11();

已经确认私有不能访问,在里面来访问就直接输出 $count、$ discount 、$ money ,实际上走到这一步可以简单的去掉。访问的就是一个函数,函数里面要访问的变量没有定义过,所以报错。

代码 04this.php:

#内部对象$this

class Saler{

#属性

public $count = 100;

protected $discount = 0.8:

private $money = 100;

public function getall(){

echo $count,$discount,$money; #全部错误:提示未定义的“变量”

}

}

$s = new Saler();

$s->getAll();

尝试之后看效果:

Notice: Undefined variable: count in D:\server\Web\04th is.php on line 13

Notice:Undefined variable: discourt in D:\serverWeb\04th is.php on line 13

Notice: Undefined variable: money in D:\server\Web\04th is.php on line 13

没有访问到结果。

注意:方法本质是定义在类内部的函数,因此受制干作用域的问题,在方法内部访问的变量系统认定为局部变量(必须内部定义或者参数传入),否则就会提示未定义

(2)类内部访问类成员,需要通过对象来进行访问

class saler{

# 属性

public $count = 100;

protected $discount = 0.8;

private $money = 100;

public function geta11(){

# 需要获取到对象名字:因为方法本身就是函数,访问外部全局变量可以通过q1oba1引入实现

global $s;

echo $s->count,$s->discount,$s->money; #正确输出

}

}

$s=new saler();

$s->geta11();

global 可以引入外边变量,引入之后可以利用对象进行访问:

#内部对象$this

class Saler{

#属性

public $count = 100;

protected $discount = 0.8;

private $money = 100;

public function getall(){

# echo $count,$discount,$money; # 全部错误:提示未定义的“变量”

# 引入对象

global $s;

echo $s->count,$s->discount,$s->money; #正确输出

}

}

$s = new Saler();

$s->getAll();

结果:1000.8100

$s 还不是内部对象,不能知道$s,不适合使用,只是一种解决方案,不是最优的解决方案

注意:上述代码规定死了以后对象只能是$s,不能有其他对象或者其他命名,所以非常不又灯

(3)使用内置对象 $this 访问

class saler{

# 属性

public $count = 100;

protected $discount = 0.8; private $money = 100;

public function geta11(){

var_dump($this);

echo $this->count.$this->discount,$this->money; #正确输出

}

}

$s = new saler();

$s->geta11();

注意:$this 代表的是对象,而 $this 所在环境为类内部的方法内部,所以 $this 对象是在类内部访问,因此可以访问所有的属性和方法,不受访问修饰限定符限制

内部有一个变量 $this,有类之后给函数特殊赋予的内置变量。

代码:

#内部对象$this

class Saler{

#属性

public $count = 100;

protected $discount = 0.8;

private $money = 100;

public function getall(){

# echo $count,$discount,$money; # 全部错误:提示未定义的“变量”

#引入对象

# global $s;

# echo $s->count,$s->discount,$s->money; #正确输出

#

#内置变量($this)

var_dump($this);

}

}

$s = new Saler();

$s->getAll();

结果:

objectSaler)#1 (3){["count*]=> int(100)["discount":prot ected]=>float(0.8)["money”:"Saler:private]=>int(100)}

编号为1说明与外面 $s 一样,整个脚本里面运行变量代表第几个对象,唯一说明指向的是同一个对象,编号只有一个。

#内部对象$this

class Saler{

#属性

public $count = 100;

protected $discount = 0.8;

private $money = 100;

public function getall(){

# echo $count,$discount,$money; # 全部错误:提示未定义的“变量”

#引入对象

# global $s;

# echo $s->count,$s->discount,$s->money; #正确输出

#

#内置变量($this)

var_dump($this);

echo $this->count,this->discount,$this->money;正确输出

}

}

$s = new Saler();

$s->getAll();

结果:1000.8100

不管外面用什么变量都可以拿到,跟变量名字没有关系。

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

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

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

①类不存在,报错;

②类存在,将类内部的属性部分复制一份,然后在内存(堆区)开辟一块内存空间,将属性放到里面,同时内部有一个指针指向类的内存空间(代码段)

③对象访问属性即访问的是对象空间里存储的部分

④对象访问方法是对象通过内部指针找到类空间中的方法,然后在内存(栈区)开辟运行(方法是函数也是结构在代码段里面,堆是放数据的,函数不是数据)

(3)$this 是系统在方法内詈的对象通用名字

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

(4)方法内部的 $this就代表调用当前 $this 所在方法的外部对象

$this的本质是函数内部的一个局部变量,只是系统自动对其进行赋值,而且一定是调用方法的对象本身(用完就没)

(5)面向对象编程代码运行内存关系

内存发生的过程:

class Saler{

//属性

public $count=100;

private $money=100;

public function getAll(){

var_dump($this);

}

}

$s =new Saler();

cho $s->count;

$s->getAll();

代码不会自动执行脚本不会执行,把东西放到内存才能运行,内存里面分为四段,栈区小效率高,数据段专门放数据效率高,堆区放大数据效率低,代码段代码运行必须先加载到代码段。请求编译会将代码全部装载到代码段里面,会有优化和处理,最终编译的结果是二进制。运行发现是一个类结构,不会执行系统会跳过,跳过会访问 $s=new Saler() 发现要执行,第一件事情去代码段寻找类 Saler 是否存在,存在可以实例化。实例化的过程会在堆里面产生一个内存区域,然后会指向类把里面所有的属性全部复制,count 直接 $count=100 ,money 会带一个 private ,再有一个 $s 指向对象,此时实例化产生,代码运行结束。

对象的内存空间与类的空间不在一起,函数在类的空间代码段里面,对象的空间里面只有属性,指针指向代码段所以能访问,$s->count 去访问属性,会找到 $s 接下来会找到所在代表的对象访问里面的 $count ,发现能访问输出结束,如果访问私有就不允许访问,因为所在的位置不是类,类里面在代码段。

访问方法,找到对象找到内存发现访问的是方法,方法在对象里面不存在顺着指针找到对应的类,然后类里面有发现有执行,把方法取出来放到内存的栈区,因为要在里面开辟栈区来运行所有的代码,运行之后系统会自动做一件事情,当方法开始执行的时候,会在里面产生一个局部变量,指向顺着代码去找,通过对象来所以指向对象。此时会发现与 $s 一样都指向对象,它们代表的是同一个对象。接下来如果要访问,因为此时方法虽然在栈里面运行,但是它有一个环境属于类内部,本质属于类内部,意味着私有的东西可以拿,因为在内部换环境、换个位置来进行运行,内存的规定必须要在这。是局部变量因为它属于函数运行的过程中,两个肯定是相等的一旦运行结束之后,函数就没了意味着从内存里面要消失,$ 自然跟着函数没了之后,指针没用所以它会断掉,此时就 $s 指向对应的,这就是结果。最后脚本要执行结束,首先清空栈里面的内存,用完了之后指针就不存在,会发现对象变成了游离内存,没有用只是它指向别人,所以系统会回收,脚本执行结束也要回收,内存又清空,这就是内存的关系。

image.png

image.png

能体现出 $this 是怎么来的, $this 代表谁,为什么能够代表谁, 类与对象的关系。

6、小结

(1)类内部方法内有一个内置对象 $this,代表访问该方法的外部对象

(2)类在实例化对象的时候要保证内存中有该类

(3)一个类可以实例化多个对象,每个对象访问成员方法时,$this 就代表对应对象

内部对象可以解决私有、隐秘的类成员的访问,私有的属性、私有的方法、受保护的都可以访问。

相关文章
|
7月前
|
Java
【JavaSE专栏65】内部类的使用,定义在其他类内部的类
【JavaSE专栏65】内部类的使用,定义在其他类内部的类
|
11月前
|
C++
C++类的学习1(一)
的定义一般包括两部分,一是类的属性,二是他所拥有的方法。类的实例化是指给类的加载并初始化过程,比如一个people类,我们具体到每一个人就是类的实例化,此外一个类可以在此类上进行扩展。比如people类,我们分为 外国people 和 中国people,那么people叫做基类,外国people叫做派生类或子类
|
11月前
|
C++
C++类的学习1(二)
的定义一般包括两部分,一是类的属性,二是他所拥有的方法。类的实例化是指给类的加载并初始化过程,比如一个people类,我们具体到每一个人就是类的实例化,此外一个类可以在此类上进行扩展。比如people类,我们分为 外国people 和 中国people,那么people叫做基类,外国people叫做派生类或子类
|
Java 编译器 PHP
C++学习笔记1:类的使用
C++学习笔记1:类的使用1. 类的定义与使用2. 类的成员变量和成员函数3. 构造函数4. 析构函数5.5 友元函数和友元类
103 0
C++学习笔记1:类的使用
|
PHP 开发者
继承|学习笔记
快速学习继承
56 0
继承|学习笔记
|
SQL 关系型数据库 数据库连接
接口继承|学习笔记
快速学习接口继承,接口只能被类去实现,如果想要规范团队,也不能把所有想要规范的东西写在一个接口里,这样会使接口臃肿,不好实现接口的类,因为有可能并不需要这么多规范。为了使接口的体系更加完整,更加具有结构性,就有了接口继承。本节的目标是理解接口的继承体系,掌握具体的接口继承实现。
92 0
接口继承|学习笔记
|
Java
java学习第十三天笔记-面向对象242-子类能继承父类的那些内容1构造方法不能被继承下来
java学习第十三天笔记-面向对象242-子类能继承父类的那些内容1构造方法不能被继承下来
43 0
java学习第十三天笔记-面向对象242-子类能继承父类的那些内容1构造方法不能被继承下来
|
Java
java学习第十三天笔记-面向对象243-子类能继承父类的那些内容2成员变量被继承下来
java学习第十三天笔记-面向对象243-子类能继承父类的那些内容2成员变量被继承下来
58 0
java学习第十三天笔记-面向对象243-子类能继承父类的那些内容2成员变量被继承下来