我们上面说过面向对象程序的单位就是对象,但对象又是通过类的实例化出来的,既然我们类会声明了,下一步就是实例化对象了。
当定义好类后,我们使用new关键字来生成一个对象。
$对象名称 = new 类名称();
<?php
class Person
{
//下面是人的成员属性
var $name; //人的名字
var $sex; //人的性别
var $age; //人的年龄 //下面是人的成员方法
function say() { //这个人可以说话的方法
echo "这个人在说话";
} function run() { //这个人可以走路的方法
echo "这个人在走路";
}
} $p1=new Person();
$p2=new Person();
$p3=new Person();
?>
$p1=new Person();
这条代码就是通过类产生实例对象的过程,$p1就是我们实例出来的对象名称, 同理,$p2, $p3也是我们实例出来的对象名称,一个类可以实例出多个对象,每个对象都是独立的,上面的代码相当于实例出来3个人来, 每个人之间是没有联系的, 只能说明他们都是人类, 每个人都有自己的姓名, 性别和年龄的属性,每个人都有说话和走路的方法,只要是类里面体现出来的成员属性和成员方法,实例化出来的对象里面就包含了这些属性和方法。
对像在PHP里面和整型、浮点型一样,也是一种数据类,都是存储不同类型数据用的,在运行的时候都要加载到内存中去用, 那么对象在内存里面是怎么体现的呢?
内存从罗辑上说大体上是分为4段, 栈空间段, 堆空间段,代码段, 初使化静态段,
①.栈空间段
栈的特点是空间小但被CPU访问的速度快,是用户存放程序中临时创建的变量。由于栈的后进先出特点,所以栈特别方便用来保存和恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个临时数据寄存、交换的内存区。用于存储占用空间长度不变并且占用空间小的数据类型的内存段,例如整型1、100、10000等在内存中占用空间是等长的,占用空间都是32位的4个字节。还有double、boolean等都可以存储在栈空间段中。
②.堆空间段
堆是用于存放进程运行中被动态分配的内存段,它大小并不固定,可动态扩张或缩减。用于存储数据长度可变或占用内存比较大的数据。例如,字符串、数组和对象就存储在这段内存中。
③.数据段
数据段用来存放可执行文件中初始化全局变量,换句话说就是存放程序静态分配的变量。
④.代码段
代码段是用来存放可执行文件的操作指令,也就是说它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作。例如程序中的函数就存储在这段内存中。
对象类型的数据就是一种占用空间比较大的数据类型,并且是占用的空间不定长的数据类型,所以对象创建完成以后被存放在对内存中,但对象的引用还是存放在栈里面的。程序在运行时,占内存中的数据是可以直接存取的,而堆内存是不可以直接存取的内存,但可以通过对象的引用名称访问对象中的成员。
程序里面不同的声明放在不同的内存段里面,
栈空间段是存储占用相同空间长度并且占用空间小的数据类型的地方,比如说整型1, 10, 100, 1000, 10000, 100000等等,在内存里面占用空间是等长的,都是64位4个字节。
那么数据长度不定长,而且占有空间很大的数据类型的数据放在那内存的那个段里面呢?这样的数据是放在堆内存里面的。
栈内存是可以直接存取的,而堆内存是不 可以直接存取的内存。
对于我们的对象来说就是一种大的数据类型而且是占用空间不定长的类型,所以说对象是放在堆里面的,但对象名称是放在栈里面的,这样通 过对象名称就可以使用对象了。
$p1=new Person();
对于这个条代码, $p1是对象名称在栈内存里面,new Person()是真正的对象是在堆内存里面的,具体的请看下图:
从上图可以看出$p1=new Person();等号右边是真正的对象实例, 在堆内存里面的实体,上图一共有3次new Person(),所以会在堆里面开辟3个空间,产生3个实例对象,每个对象之间都是相互独立的,使用自己的空间,在PHP里面,只要有一个new这个关键字出现就会实例化出来一个对象,在堆里面开辟一块自己的空间。
每个在堆里面的实例对象是存储属性的,比如说,现在堆里面的实例对象里面都存有姓名、性别和年龄。每个属性又都有一个地址。
$p1=new Person();等号的左边$p1是一个引用变量,通过赋值运算符“=”把对象的首地址赋给“$p1“这个引用变量, 所以$p1是存储对象首地址的变量,$p1放在栈内存里边,$p1相当于一个指针指向堆里面的对象, 所以我们可以通过$p1这个引用变量来操作对象, 通常我们也称对象引用为对象。
验证:
class Person{
public $name;
} $obj1 = new Person();
$obj1->name = "test1";
echo $obj1->name;
$obj2 = $obj1;
$obj2->name = "test2";
echo $obj1->name;
echo $obj2->name;
通过测试结果来看,解释是对的。
$p1 是对象的指针而不是对象本身, obj2和 obj1都指向同一块内存,同一个对象。这一点和OOP语言是一样
object(Person)[2]
public 'name' => string 'test2' (length=5)
object(Person)[2]
public 'name' => string 'test2' (length=5)
可见对象的ID号是一个
如果想得到一个对象的副本,用$obj2 =clone $obj1; 用了clone后会产生一个新对象,分配内存,独立于原来的obj1
参见手册此页 http://www.php.net/manual/zh/language.oop5.cloning.php
$obj2 = $obj1;
$obj2 = &$obj1;
一样的效果,一样的解释?
对于object来说,是一样的。 对于普通的变量是不一样的。
$a = 1;
$b = $a;
$c = &$a;
不一样的