面向对象
一、
类:是用于描述“某一些具有共同特征”的物体的概念,是某一类物体的总称。
通常,一个类所具有的共同特征包括2大方面的信息:
外观,形状,描述,数据。。。。。属性
行为,动作,功能。。。。。。。。方法。
对象:是指一个具体的“物体”,该物体隶属于某个“类别”(类)。
通常,对象离不开类,没有类,就不能有对象。
//定义一个类
class C1{
//类中有一些属性(就是变量):
var $name = '匿名';
var $sex = "未知";
var $age = 18;
//类中有一些方法(就是函数)
function f1(){
echo "<br />" . $this->name . "在执行函数(方法)f1";//$this就是自己。
}
//类中有一些常量(类常量)
const PI = 3.14;
}
//该类创建好之后,只是一个“死代码”(类似一个变量定义好)
//我们通常需要使用该类才能发挥该类的作用
//第一个使用就是“创造该类的一个对象”
$person1 = new C1();//C1是类名,当然如果用Human就更好。
//此时$person1就是一个“对象”,是有C1这个类所创建出来的对象
$person2 = new C1();
$person1->name = "张三"; //给属性赋值(类似给变量赋值)
$person1->sex = "男"; //同理
$str1 = $person1->name; //取得属性值(类似取得变量值)
echo "{$str1}的性别为:" . $person1->sex;
echo ",年龄为:" . $person1->age;
$person1->f1();
$person2 = new C1();
$CName = "C1";
$person3 = new $CName(); //可变类(名)
$person4 = new $person3; //通过对象创建该类的新对象
二、对象的创建形式
方式1:
$对象名1 = new 类名(); //对象名就是变量名;类是应该定义过了
方式2:
$name = "C";
$person = new $name();//可变类(名)
方式3:
$对象名3 = new self; //self指代类本身,这行代码只能在类内部方法中使用。
方式4:通过对象创建对象
new 对象名;//创建该对象所属类的一个新对象
三、对象的传值
值传递: 传递的时候,拷贝的是数据本身。默认都是值传递。
结果:传递完之后,有了2份同样的数据,但两个变量“相互独立”没有关系。
引用传递: 传递的时候,拷贝的是引用关系。需要使用“&”才能实现引用传递。
结果:传递完之后,数据仍然只有一份,但是两个变量共同指向该数据。
class P{
var $v1 = 10;
}
$p1 = new P(); //也可以写成$p1 = new P;
$p2 = $p1; //这是值传递
$p1->v1 = 20; //修改对象$p1
echo "<br />p1->v1 为:" . $p1->v1;
echo "<br />p2->v1 为:" . $p2->v1;
echo "<br />对象p1标识符为:";
var_dump($p1);
echo "<br />对象p2标识符为:";
var_dump($p2);
unset($p1);
echo "<br />p1中的v1的值为:" . $p1->v1;
echo "<br />p2中的v1的值为:" . $p2->v1;
$p3 = new P();//这个时候才是创建了一个新对象
//并同时会赋予一个新的标识符
$p4 = &$p3; //这是引用传递
echo "<br />对象p3标识符为:";
var_dump($p3);
echo "<br />对象p4标识符为:";
var_dump($p4);
$p3 = new P(); //再给$p3重新复制
$p3->v1 = 100; //修改$p3
echo "<br />p3中的v1的值为:" . $p3->v1;
echo "<br />p4中的v1的值为:" . $p4->v1;
echo "<br />对象p3标识符为:";
var_dump($p3);
echo "<br />对象p4标识符为:";
var_dump($p4);
对象变量进行普通传值的时候,复制的是对象变量中所存储的“对象标识符”
四、属性
属性就是放在一个类中的变量。
定义形式:
形式1: var $v1 ; //定义不赋值
形式2: var $v2 = 2; //定义的同时可以赋值,该值只能是“直接值”,常量(值)
//不能是变量值,也不能是“计算表达式”
形式3: public $v1;
形式4: public $2 = 2; //其实var是“public”一个别名,正式用public更好。
方法前可以加修饰词:public, protected,private,省略就算“public”
五、方法中$this关键字
$this是一个“伪对象”,代表当前所属类的当前对象。
一个系统函数:get_class(对象)
作用:获得某个对象的“所属类名”——结果只是一个类名字符串。
$class_name = get_class($p1); //结果可能是:”Person”
静态属性:
在定义属性的时候,前面加上关键字:static,此时就是静态属性。
静态属性就是:只隶属于类本身——也可以看做是所有对象的“共有数据”。
静态属性的使用:
通过特殊的语法:::(双冒号语法,也叫范围解释符)
类::$静态属性名;
对比普通属性的使用:
对象->普通属性名; //普通属性也可以叫做“实例属性”,相应的,对象也叫“实例”
静态方法
如果在一个方法的前面加上static关键字修饰,则就变成了静态方法。
静态方法同样隶属于类,而不是隶属于具体对象。使用方法跟静态属性类似:
类名::静态方法名();
从理念上,可以认为,静态方法是只隶属于类,而为所有对象所“共有”。
如果通过类名来调用静态方法,则该方法中不可以出现$this关键字。
注意1:$this在静态方法中不能使用。
六、构造方法
构造方法是“创建”对象的时候会自动调用。
构造方式是类中的一个“特殊”方法,其作用是在实例化一个对象的同时,给该对象的属性赋值,使之一创建完成,就具有了其本身的特有数据(属性值)。
1,该方法名字是固定的,为:__construct();
2,该方法必须是普通方法(不能是静态方法)
3,通常该方法应该是public
4,通常该方法中使用$this这个关键字来对属性进行赋值
5,当new 类名()的时候,其实是在调用该构造方法
6,如果一个类中定义了构造方法,则实例化该类时就会调用该方法,且实例化时的参数需要跟构造方法的参数匹配
class P{
public $name = "匿名";
public $age = 18;
//定义一个方法,该方法可以进行“自我介绍”
function intro(){
echo "<br />hi,大家好,我叫 " . $this->name;
echo ",今年 " . $this->age . " 岁";
}
function __construct($n, $a){
$this->name = $n;
$this->age = $a;
}
}
//$p1 = new P(); //此时这里出错
//$p1->name = '张三';
//$p1->age = 20;
//$p1->intro();
//上述做法如果可以在创建对象的同时,
//就给该对象设定其特有的值,就方便了,比如:
$p2 = new P('李四', 22);//此时可以看作是在调用方法__construct(),对方法进行初始化、赋值
$p2->intro();
七、
析构方法
析构方法是“销毁”对象的时候会自动调用。
说明:
1,析构方法通常不太需要去定义。
2,析构方法不能调用。
3,析构方法不能有形参。
4,析构方法中可以用于清理一些在php代码结束后不能清理的数据,如生成的文件。
对象销毁的几个情形:
脚本程序运行结束,自动销毁;
明确地unset()一个对象变量,则被销毁;
改变对象变量的值,被销毁;
实际上,更本质来说,当一个对象(new 出来的对象)没有任何一个变量指向它的时候,该对象就会被自动销毁——自然,如果整个程序结束,也会销毁。
class P{
public $v1 = 1;
function __construct($n){
$this->v1 = $n;
echo "<br />被创建了";
}
function __destruct(){
echo "<br />被销毁了";
}
}
echo "<h3>1</h3>";
$p1 = new P(5);
$p2 = new P(15);
$p3 = new P(25);
unset($p1); //被销毁
echo "<h3>2</h3>";
$p2 = 3; //可以等于任意一个数据
//目的是让$p2原来所指向的对象“没有所属”
//此时就会发生该原来对象“销毁”情形
//不过,如果原来有代码$p2a = $p2,
//则此时又不会销毁该对象
echo "<h3>3</h3>";