面向对象
类
类中的成员
一个类的内部可以有3种代码
- 属性
属性就是放在一个类中的额变量
//定义形式
形式1:var $v1 ; 定义不赋值
形式2:var $v2 = 2 ; 定义的同时可以赋值,该值只能是直接值,常量值,不能是变量,也不能是计算表达式;
形式3: public $v1 ;
形式4: public $v2 = 2 ; 其实var 是public一个别名,正式用public更好;
错误定义属性的方式
$v1 = 1 ; 不能没有var或public
var $v2 = 1+2 ; 不能是表达式
public $v3 = $v2 ; 不能是变量赋值
使用形式:
$对象->属性名 //注意:属性名前面没有$
- 方法
//方法就是定义在类中的函数,但函数前可以使用public , protected , private修饰,也可省略
//方法定义和函数定义一样,使用是通过类或类的对象来进行
//方法中的$this关键字具有特定含义,表示调用该方法的对象
class Person {
public $name = 'tom' ;
function fn($age){
echo "i am $this->name and $age years old" ;
}
}
$p = new Person() ;
$p->fn(19) ; //i am tom and 19 years old
- 类常量
静态属性
在定义属性的时候,前面加上关键字:static,此时就是静态属性
一般属性的值是隶属于该类的某个对象
静态属性只隶属于类本身,也可以看做所有对象的共有数据
使用静态属性通过特殊语法::(双冒号)
类::$静态属性名
class Person {
static $v1 = 100 ;
}
Person::$v1 = 200 ; //修改静态属性值
$p1 = Person::$v1 ; //获取静态属性值
echo $p1 ; //200
实例也可以修改静态属性
class Person {
static $v1 = 100 ;
}
$p1 = new Person() ;
$p1::$v1 = 300 ;
echo $p1::$v1 ; //300
静态方法
- 静态方法中不能使用$this
- 静态方法中不应调用非静态方法
在一个方法前面加上static,就变成了静态方法
静态方法同样隶属于类,不属于某个对象,使用和静态属性类似
class Person {
public $v1 = 100 ;
static $v2 = 200 ;
static function fn(){
echo Person::$v2 ; //200
// echo $this->$v1 ; //报错 ,
}
}
Person::fn() ;
- 实例也可以调用静态方法,但是不推荐
- self
self 代表当前类
通常只能在某个类的某个方法内部代表该类的名称
class Person {
static function fn(){
return new self ;
}
}
$p1 = Person::fn() ;通过静态方法fn得到该类的一个新对象
系统函数get_class() 获取某个对象所属类名
class Person {
static $v1 = 100 ;
}
$p1 = new Person() ;
echo get_class($p1) ; //Person
构造方法
- 构造方法是类中的一个特殊方法,作用是在实例化一个对象的同事给该对象的属性赋值,使之一创建就具备了特有数据
- 该方法名字是固定的: __construct;
- 该方法必须是普通(不能是静态方法) ;
- 通常该方法应该是public ;
- 通常该方法中使用$this这个关键字来对属性进行赋值;
- 当new 类名() 的时候,其实是在调用该构造方法;
- 如果一个类中定义了构造方法,则实例化该类时就会调用该方法,且实例化时的参数需要跟构造方法的参数匹配
- 如果一个类中没有定义构造方法,则会自动调用其父类的构造方法(如果有),则实例化时的参数需跟父类的构造方法的参数匹配。
- 也可以再当前类的构造方法中调用父类的构造方法:parent::__construct() ;
- 构造方法适用于创建对象时对该对象做一些初始化的工作;
- 定义形式:[访问修饰符] function __construct(){} //访问修饰符通常总是需要public(或省略)
class Person {
public $name = ' ' ;
public $age = 123 ;
function say(){
echo "i am $this->name , am $this->age" ;
}
function __construct( $n , $a ){
$this->name = $n ;
$this->age = $a ;
}
}
$p1 = new Person( 'jack' , 22 ) ; //可以看做时调用__construct()
$p1->say() ; //i am jack , am 22
析构方法
- 析构方法是在一个对象被销毁的时候自动调用的方法
- 析构方法适用于销毁对象时对对象中使用的一些资源进行清理(销毁),不过实际上现代PHP已经具备了垃圾回收机制,一般无需清理;
- 定义形式,function __destruct(){} ; 注意:只能是public的,且不能有参数;
- 调用形式:无需在代码中手动调用,在代码运行结束时会自动调用该方法;
- 如果一个类中定义了析构方法,则销毁对象时就会调用该方法;
- 如果一个类中没有定义析构方法,则销毁对象时就会调用其父类的析构方法(如果有)
定义一个类
//这是一个人员类
class Person {
//类中的属性(变量)
var $name = 'tom' ;
var $age = 20 ;
//类中的方法(函数)
function fn(){
echo '函数调用';
}
//类中的常量
const PI = 3.14 ;
}
使用类
//定义类
class Students {
public $name = 'tom' ;
public $age = 20 ;
public $addr = 'usa' ;
function say(){ //定义是方法不需要$符
echo "i am $this->name" ;
}
}
//使用类
$s1 = new Students() ; //也可以写成new Students ;
$s1->name = 'jack' ; //使用属性的时候不需要加$符号
$s1->age = 22 ;
$s1->addr = 'chn' ;
$s1->say() ; //i am jack
对象创建的基本形式
- $person1 = new Person() ;
- $person2 = new self ; //只能在类内部方法使用
class Person {
public $name = 'tom' ;
public $age = 20 ;
public $addr = 'usa' ;
function say(){ //定义是方法不需要$符
return new self ;
}
}
- new 对象名() //创建该对象所属类的一个新对象
class Students {
public $name = 'tom' ;
public $age = 20 ;
public $addr = 'usa' ;
function say(){ //定义是方法不需要$符
echo "i am $this->name" ;
}
}
//使用类
$s1 = new Students() ;
$s2 = new $s1 ;
- new 变量名() //变量名存储的是类
class Students {
public $name = 'tom' ;
public $age = 20 ;
public $addr = 'usa' ;
function say(){
echo "i am $this->name" ;
}
}
$std = "Students" ;
$s1 = new $std() ;
$s1->name = 'jim' ;
$s1->say() ; //i am jim
- 类名::getNew() //定义类的一个静态方法用与获取该类的一个对象
对象的传值
php中变量传值有两种方式
- 值传智,传递的时候拷贝数据本身,默认都是值传递,传递完成之后有2分同样的数据并且相互独立
- 应用传递,传递的时候拷贝的是引用关系,需要使用&才能实现引用传递。传递完成之后,数据任然只有一份,但是两个变量共同指向该数据。
class Students {
public $name = '学生' ;
}
$s1 = new Students ;
$s1->name = '学生1' ;
$s2 = $s1 ; //这是值传递
$s2->name = '学生2' ;
//只更改了$s2的name ,但是$s1的name也改变了
echo "$s1->name <br/>" ; //学生2
echo "$s2->name <br/>" ; //学生2
- 验证对象的值传递
class Students {
public $name = '学生' ;
}
$s1 = new Students ;
$s1->name = '学生1' ;
$s2 = $s1 ; //这是值传递
$s2->name = '学生2' ;
unset($s1) ; //断开$s1的标识符
echo "$s1->name <br/>" ; //报错
//由于在复制的时候是值传递,$s2里的标识符是拷贝一份过来的,所以在$s1断开的时候不会影响到$s2
echo "$s2->name <br/>" ; //学生2
对象存储和普通变量存储的区别
对象变量进行普通传值的时候,复制的是对象变量中所存储的‘对象标识符’