一、简介
自 php 5 起完全重写了对象模型以得到更佳性能和更多特性。这是自 php 4 以来的最大变化。php 5 具有完整的对象模型。
php 5 中的新特性包括访问控制,抽象类和 final 类与方法,附加的魔术方法,接口,对象复制和类型约束。
php 对待对象的方式与引用和句柄相同,即每个变量都持有对象的引用,而不是整个对象的拷贝。
二、基本概念
1.class
每个类的定义都以关键字 class 开头,后面跟着类名,后面跟着一对花括号,里面包含有类的属性与方法的定义。
类名可以是任何非 php 保留字的合法标签。一个合法类名以字母或下划线开头,后面跟着若干字母,数字或下划线。以正则表达式表示为:[a-za-z_\x7f-\xff][a-za-z0-9_\x7f-\xff]*。
一个类可以包含有属于自己的常量,变量(称为“属性”)以及函数(称为“方法”)。
example #1 简单的类定义
<?php
class simpleclass
{
//声明属性
public $var = '1';
//声明方法
public function displayvar(){
echo $this->var;
}
}
?>
当一个方法在类定义内部被调用时,有一个可用的伪变量 $this。$this 是一个到主叫对象的引用(通常是该方法所从属的对象,但如果是从第二个对象静态调用时也可能是另一个对象)。
example #2 $this 伪变量的示例
<?php
class a
{
function foo()
{
if(isset($this)){
echo '$this is defined (';
echo get_class($this);
echo ')<br>';
}else{
echo '$this is not defined.<br>';
}
}
}
class b
{
function bar()
{
//如果开启了e_strict这一行会有警告提示
a::foo();
}
}
$a = new a();
$a -> foo();
//如果开启了e_strict这一行会有警告提示
a::foo();
$b = new b();
$b -> bar();
//如果开启了e_strict这一行会有警告提示
b::bar();
?>
输出结果:
$this is defined (a)
$this is not defined.
$this is defined (b)
$this is not defined.
2.new
要创建一个类的实例,必须使用 new 关键字。当创建新对象时该对象总是被赋值,除非该对象定义了构造函数并且在出错时抛出了一个异常。类应在被实例化之前定义(某些情况下则必须这样)。
如果在 new 之后跟着的是一个包含有类名的字符串,则该类的一个实例被创建。如果该类属于一个名字空间,则必须使用其完整名称。
example #3 创建一个实例
<?php
$instance = new simpleclass();
//也可以这样做:
$classname = "foo";
$instance = new $classname(); //foo()
?>
在类定义内部,可以用 new self 和 new parent 创建新对象。
当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。此行为和给函数传递入实例时一样。可以用克隆给一个已创建的对象建立一个新实例。
example #4 对象赋值
include_once('class1.php');
$instance = new simpleclass();
$assigned = $instance;
$reference = & $instance;
$instance -> var = '$assigned will have this value';
$instance = null; //$instance和$reference变成null
var_dump($instance);
var_dump($reference);
var_dump($assigned);
输出结果是:
null
null
object(simpleclass)#1 (1) { ["var"]=> string(30) "$assigned will have this value" }
php 5.3.0 引进了两个新方法来创建一个对象的实例:
c
lass test
{
static public function getnew()
{
return new static;
}
}
class child extends test
{}
$obj1 = new test();
$obj2 = new $obj1;
var_dump($obj1 !== $obj2);
$obj3 = test::getnew();
var_dump($obj3 instanceof test);
$obj4 = child::getnew();
var_dump($obj4 instanceof child);
输出结果:
bool(true)
bool(true)
bool(true)
3.extends
一个类可以在声明中用 extends 关键字继承另一个类的方法和属性。php不支持多重继承,一个类只能继承一个基类(与java一样都是单继承)。
被继承的方法和属性可以通过用同样的名字重新声明被覆盖。但是如果父类定义方法时使用了 final,则该方法不可被覆盖。可以通过 parent:: 来访问被覆盖的方法或属性。
当覆盖方法时,参数必须保持一致否则 php 将发出 e_strict 级别的错误信息。但构造函数例外,构造函数可在被覆盖时使用不同的参数。
example #6 简单的类继承:
class extendclass extends simpleclass
{
//重写父类的方法
function displayvar()
{
echo "extending class<br>";
parent::displayvar();
}
}
$extended = new extendclass();
$extended -> displayvar();
输出结果:
extending class
1
4.::class
自 php 5.5 起,关键词 class 也可用于类名的解析。使用 classname::class 你可以获取一个字符串,包含了类 classname 的完全限定名称。这对使用了 命名空间 的类尤其有用。
example #7 类名的解析
namespace ns{
class classname{}
echo classname::class;
}
输出结果:
ns\classname