相关概念
术语 | 说明 |
类(class) | 具有相同特征和行为的对象 |
对象(obj) | 具有特征和行为的个体 |
特征 | 属性,也就是变量 |
行为 | 方法,也就是函数 |
类的语法
/**
*实例:类的书写格式以及实例化(创建对象)
*/
class Name{//不需要写括号 ,命名的每个单词首字母大写
public a; //属性
funtcion A(){ //方法
}
}
#类的实例化,结果是对象
$obj= new Name(); //返回对象
var_dump($obj);
访问对象
使用特殊操作符”->”访问对象的成员 ,对象里面的所有的成员都要用对象来调用,包括对象的内部成员之间的调用,PHP 提供了一个本对象的引用$this
外部访问: | 对象->成员 |
内部访问: | $this->成员 |
/**
*实例:访问对象中的成员(属性和方法)
*/
class Human{
public $name;
public $sex;
public $age;
function self(){
echo "我是{$this->name},性别:{$this->sex},{$this->age}岁";
}
}
#实例化对象
$xiaoming=new Human();
#给属性赋值
$xiaoming->name ='小明';
$xiaoming->sex='男';
$xiaoming->age='23';
#访问属性
echo $xiaoming->name;
#访问方法
$xiaoming->self();
常量成员
不会在类中改变的值。使用关键字const声明类的常量,注意不能在方法里声明,只能在方法内部访问。
外部访问: | 类名或对象::常量名 |
内部访问: | self::常量名 |
/**
* 实例:定义和访问类常量
*/
class ClassName{
const NAME='value'; //定义一个常量
function abc(){
echo self::NAME; //方法内部调用常量
}
}
$obj=new ClassName(); //实例化
$obj->abc(); //调用类的abc方法
echo $obj::NAME; //使用对象名外部调用
echo ClassName::NAME; //直接使用类名外部调用
静态成员
使用static 关键字声明属性,也可以声明方法,使用了静态,有以下特点
- 静态成员可以不实例化类而直接访问
- $this 在静态方法中不可用
- 静态属性不可以由对象通过 -> 操作符来访问
- 静态属性和静态方法的访问与常量的访问方式相同
- 静态的成员属于类所有,可以在方法里声明静态属性,但不能直接调用
外部访问: 类名或对象::静态属性名或方法名 内部访问: self::静态属性名
/**
*实例:静态属性与方法的声明和访问
*/
class ClassName{
static $name='value';
static function abc(){
echo self::$name;
}
}
$obj=new ClassName();
#访问静态属性
echo $obj::$name; //实例化访问
echo ClassName::$name; //不实例化访问
#访问静态方法
echo $obj::abc(); //实例化访问
echo ClassName::abc(); //实例化访问
构造函数
在类实例化后立即自动调用执行。一般初始化某些属性,或执行某些方法的函数。
/**
*应用实例
*/
class Human{
public $name;
public $sex;
public $age;
function __construct($name,$sex,$age=0){
$this->name=$name;
$this->sex=$sex;
$this->age=$age;
}
function self(){
echo "我是{$this->name},性别:{$this->sex},{$this->age}岁";
}
}
$xiaoming=new Human('小明','男',16);
$xiaoming->self();
$xiaoqiang=new Human('小强','男');
$xiaoqiang->self();
析构函数
php5中引入了析构函数。在类销毁之前自动执行,一般应用于重置、超出限制等场景。
/**
*应用实例
*思考: 为什么小强比小明先消失?
*原因:与内存存储有关,先声明的后销毁
*/
class Human{
public $name;
function __construct($name=''){
$this->name=$name;
}
function self(){
echo "我是{$this->name}<br>";
}
function __destruct(){
echo "{$this->name}消失<br>";
}
}
$xiaoming=new Human('小明');
$xiaoming->self();
$xiaoqiang=new Human('小强');
$xiaoqiang->self();
OOP特点
继承
继承是指在一个类的基础上再建立另一个新的派生类,新的派生类成为子类,继承了父类的所有类成员,并且可以重新定义或加进新的属性和方法, 提高了代码重用性。
- 在PHP中,类继承通过 extends 关键字实现
- 继承自其他类的类称为子类(child class 或 subclass)
- 子类所继承的类称为父类( parent class) 或 基类 (base class)
- 父类可以被多个子类所继承
- 子类方法与父类方法同名时,子类方法覆盖父类方法,若要父类方法不被覆,则使用 paren关键字 格式 :paren::testA();
/**
* 实例:定义 Test 类,并继承自 TestParent 类
*/
class TestA {
public $testA1;
function testAFun(){
echo "我是父类的方法和{$this->testA1}";
}
}
Class TestB extends TestA {
public $testB1;
function testBFun(){
paren::testAFun();
echo '我是子类的方法和{$this->testB1}';
}
}
#访问、设置继承父类的方法和属性
$obj=new TestB ();
$obj->testA1='属性';
$obj->testBFun();
封装
封装是指使用修饰符对属性和方法进行限制,尽可能隐蔽对象的内部细节。对外形成一个边界,只保留有限的对外接口使之与外部发生联系。类的封装性具有以下优点
- 隐藏类的实现细节,让使用者只能通过事先定义好的方法来访问数据。
- 可以方便的加入逻辑控制,进行数据检查,限制对属性的不合理操作
- 便于修改增强代码的可维护性
访问修饰符是指允许开发人员对类成员的访问进行限制,这是PHP5的新特性。
修饰符 | 说明 | 作用域 |
public | 公共修饰符 | 没有访问限制 |
private | 私有修饰符 | 只有本类没有访问限制,子类也无权限访问 |
protected | 保护修饰符 | 只有本类、子类没有访问限制,被子类继承的protected成员,在子类外部同样不能被访问 |
/**
* 实例:类的封装,本例子的属性需要逐个测试
*/
class TestA {
public $test1; //公共
private $test2; //私有
protected $test3; //保护
function __construct($test1){
$this->test1=$test1;
$this->test2=$test2;
$this->test3=$test3;
}
function testFun1(){
echo "我是父类的方法和{$this->$test1}";
}
}
Class TestB extends TestA {
function testFun(){
echo "我是子类的方法和{$this->test1}";
}
}
$objA=new TestA('TEST1');
$objA->testFun1();
#访问、设置继承父类的方法和属性
$objB=new TestB('TEST1');
$objB->testFun();
多态
多态性是指在父类的属性或行为被子类继承之后,可以具有不同的数据类型或表现出不同的行为。使用一个函数封装具有相同方法的对象,通过设置函数的参数约束。
class TestA{
public $test1; //公共
function __construct($test1){
$this->test1=$test1;
}
function testA1(){
echo "父类A1方法调用的属性值:{$this->test1}";
}
}
Class TestB extends TestA {
function testB1(){
echo "子类的方法调用的属性值:{$this->test1}";
}
}
#使用同个函数封装具有相同类成员的不同对象
function test($obj){
$obj->testA1();
$obj->testB1();
}
$obj=new TestB('哈哈');
test($obj);
#可以增加父类或祖先类的约束(PHP使用少)
Class TestC {
public $test1; //公共
function __construct($test1){
$this->test1=$test1;
}
function testA1(){
echo "父类A1方法调用的属性值:{$this->test1}";
}
function testB1(){
echo "子类的方法调用的属性值:{$this->test1}";
}
}
function test(TestA $obj){
$obj->testA1();
$obj->testB1();
}
$obj=new TestB('哈哈'); //正确实例
/*$obj=new TestC('哈哈');//错误实例*/
test($obj);
命名空间
PHP5.3新加的特性,为了避免产生类名冲突而产生的。
- 命名空间采用namespace来声明,并且namespace之前不能有输出
- 在如果一个文件中包含命名空间,它必须在其它所有代码之前声明命名空间。
- 有三种类型的代码受命名空间的影响,它们是:
类
,函数
和常量
。- 不提倡在同一个文件中定义多个命名空间
- use 别名使用
/**
*实例:命名空间(待验证)
*/
#建立wengdo.php 代码如下:
namespace wengdo; //定义了一个名字空间
function time(){
return "wengdo里面的time函数";
}
const PHP_OS='wengdo里面的常量';
class Test{
public function __construct(){
echo 'wengdo里面的Test类';
}
}
#建立tests.php 代码如下:
include('wengdo.php');
echo time(); //非限定名称
echo "<br />";
echo wengdo\time(); //限定名称
echo "<br />";
echo \wengdo\time(); //完全限定名称
$p1=new wengdo\Test();
use wengdo as hehe; //使用别名
$p1=new hehe\Test();
自动加载
通常一个类都以有规律的命名保存为一个PHP文件,当PHP文件中需要调用一个类时,通过include把这个文件引入。当需要引入多个类文件时,很繁琐,PHP5提供了一个__autoload()来解决这个问题。
在组织定义类的文件名时,需要按照一定的规则,文件名与类名保持一致,加上统一的前缀或后缀形成文件名,如:
- class_db.php
- Abc_class.php
- Abc.class.php
/**
*实例: 自动加载文件class_name中的类(待验证)
*/
function __autoload($class_name) {
include("$class_name"."_class.php");
}
#实例化对象时,如果类不存在,则调用__autoload()函数,其参数为类名
$db = new employee ();