PHP基础知识(二、面向对象)

PHP面向对象基本概念

1
2
3
4
5
6
7
8
9
class People{
public $name = 'nobody';
public function cry(){
echo '呱呱坠地';
}
}
$man = new Prople();
echo $man->name;
echo $man->cry();

属性与方法的注意点

  • 对于属性值,可以在声明属性的同时进行赋值,也可以先声明并不进行赋值,如果不复制,属性的默认值为null;

  • PHP的属性值必须是一个“直接的值”,不能是表达式(如:1+2)的值,或者函数的返回值等等

  • PHP中的函数不能重复定义(即函数名不能重复),但是全局函数名可以和类中的方法名一样

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Clock{
public function time(){
echo '现在时间戳是11111111';
}
public function time2(){
echo '现在时间戳是',time();
}
public function time3(){
echo '现在时间戳是',$this->time();
}
}
$c = new Clock();
$c->time(); //现在时间戳是11111111
$c->time2(); //调用系统函数,输出真实的时间戳
$c->time3(); //现在时间戳是11111111

构造函数详解

在类中,有一个构造函数,就是用来初始化对象用的,利用构造函数,就有机会操作对象,并改变它的值

工作原理:生成对象时,先按类的声明,把属性凑齐,再用__construct()去影响,再返回该对象

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Human{
public function __construct($name,$gender){
$this -> name = $name;
$this -> gender = $gender;
}
public $name = null;
public $gender = null;
}
$a = new Human('张飞','男');
$b = new Human('李四','男');
$c = new Human('黛玉','女');

echo $a -> name,"<br />"; //张飞
echo $b -> name,"<br />"; //李四
echo $c -> name,"<br />"; //黛玉

  • 构造函数的作用时机:每当new一个对象,就会自动对new出来的新对象发挥作用

  • new ClassName()传的参数,是给构造函数用的

  • new ClassName()也可以不传参,但前提是与构造函数里的参数保持一致

  • 一个类中,只允许存在一个构造函数

析构函数

构造函数是在对象产生的时候,自动执行

析构函数是在对象销毁的时候,自动执行

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Human{
public function __construct(){
echo "出生喽!";
}
public $name = null;
public $gender = null;
public function __destruct(){
echo "还是跪了!";
}
}
$a = new Human();
$b = new Human();
$c = new Human();
$d = new Human(); //4生4死
unset($a); // 出生喽! 还是跪了!
$b = false; // 出生喽! 还是跪了!
$c = null; // 出生喽! 还是跪了!

对象的销毁:

  • 显式销毁:unset(),赋值为null,都可以。

  • PHP是脚本语言,在代码执行到最后一行时,所有申请的内存都要释放,自然,对象的内存也要释放,所以对象也被销毁了

析构函数与回收机制详解

在上例中,如果将对象$b进行如下赋值操作$b = true,还是会立即触发析构函数,原理如下:

image

  • 改变了$b的指向,原来内存中的Object对象就没有人指向它,所以会被回收
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Human{
public $name = null;
public $gender = null;
public function __destruct(){
echo "死了!";
}
}
$a = $b = $c = new Human();
unset($a);
echo 'unset a<br />';
unset($b);
echo 'unset b<br />';
unset($c);
echo 'unset c<br />';
/*
unset a
unset b
死了
unset c
*/

原理如下:

image

this绑定

1
2
3
4
5
6
7
8
9
10
11
12
class Human{
public $name = 'lisi';
public function who(){
echo $this -> name;
}
public function test(){
echo $name;
}
}
$a = new Human();
echo $a -> name,'<br />'; //lisi
$a -> who(); //lisi
  • 当一个对象调用其方法时,该方法执行之前,先完成一个绑定

  • $this绑到调动此方法的对象【睡调用就绑定谁】

  • 在PHP中,方法想访问成员变量必须要使用this进行绑定,而在Java和C++等其他语言中,可以省略,默认访问成员变量,如test()方法在PHP中不合法,但在Java和C++中却可以

封装的概念

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
class Human{ 
public $money = 1000;
}
$lisi = new Human();
echo $lis -> money; //1000

//对属性进行封装
class Human{
private $money = 1000;
public fuction shoeMoney(){
return $this -> money * 0.8;
}
}
$lisi = new Human();
echo $lis -> shoeMoney();
  • 私有的money的属性只能通过相应的方法进行访问,这就是封装在属性上的体现。在方法上的体现也是一个道理。

权限修饰符

用来说明:属性/方法的权限特点,写在属性/方法的前面,PHP共有3个权限修饰符

  • private:私有的,其定义的属性和方法只能在类内部进行访问

  • protect:保护的

  • public:公共的,其定义的属性和方法在任意位置都可以访问

1
2
3
4
5
6
7
8
9
10
11
class Human{
public $name = 'lisi';
private $money = 1000;
public function shoeMoney(){
echo $this -> money;
}
}
$a = new Human();
echo $a -> name,'<br />'; //lisi
echo $a -> money; //私有属性,在类的外部不可读写
$a -> shoeMoney(); //1000

权限控制的BUG

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Human{
private $money = 1000;
public function getMoney($people){
return $people -> money;
}
public function setMoney($people){
echo $people -> money -= 500;
}
}
$zhangsan = new Human();
$lisi = new Human();
echo $lisi -> getMoney($zhangsan);
$lisi -> setMoney($zhangsan);
print_r($zhangsan);
  • 从生活的角度看,李四读取和改变张三的钱,是不合理的

  • 这是因为在PHP中,并不是以对象为单位俩控制权限,而是以类为单位进行权限控制封装MySQL类

继承的概念

1
2
3
4
5
6
7
8
9
10
class Human{
public $height = 160;
public function cry(){
echo '呜呜呜呜';
}
}

class Stu extends Human{}
$xiaoming = new Stu();
$xiaomming -> cry(); //呜呜呜呜
  • 以一个类为父类,另一个类作为其子类,子类在继承父类的属性和方法的基础上,可以进一步的增添和修改

  • 一个子类只能有一个父类

继承注意事项

  • 私有属性可以理解为不能被继承(其实可以被继承,但无法操作)

  • public和protected都可以继承,并拥有访问和修改的权限

  • 继承时,权限只能越来越宽松或者保持不变,不能越来越严格

构造方法的继承

构造方法也是可以继承的,new子类时,如果构造方法继承过来,当然也要自动执行,但继承过来,子类重写了,自然执行子类的构造方法(父类的构造方法就不在调用)

public、protected、private权限详解

  • Public权限最为宽松,在任何地方都可以访问
  • Protected在自身被定义的类和其子类中可以被访问
  • Private只能在其被定义的类中访问
  • 在PHP中,如果属性和方法前面什么参数也不写,即public/protected/private都不写,则理解为public