PHP面向对象基础

类的声明

  • 定义类:

[修饰类的关键字] class 类名
{
    成员
}
  • 类文件的命名: 类名.class.php
  • 注意事项:
  • 类的成员要和类名相关
  • 类的成员属性前面必须要有修饰词, 不知道写什么就写 var
  • 类的成员对象在定义时可以设置初值, 但建议不要
  • 类的成员默认访问权限是: public

实例化类


$对象名 = new 类名([参数列表]);
$对象名 = new 类名;

对象在内存中的分配

内存的划分

  • 栈: 存放程序中临时创建的变量, 空间小但被 CPU 访问的速度很快。用于储存占用空间不变且占用空间小的数据类型的内存段
  • 堆: 用于存储进程运行中被动态分配的内存段, 大小不固定, 可以动态扩张或缩减。用于存储数据长度可变或占用内存较大的数据
  • 初始化数据段: 用于存放可执行文件中已初始化的全局变量, 即程序静态分配的变量
  • 代码段: 存放可执行文件的操作指令, 即可执行文件在内存中的镜像, 访问类型为只读

对象的存储

对象存储在堆内存中, 在堆中的地址储存在栈上, 变量对应的是栈上的空间

调用对象的成员

  • 对象->属性
  • 对象->方法

构造函数

  • 作用: 为对象初始化属性
  • PHP4 中使用, 普通方法

function 类名()
{
    函数体
}
  • PHP5 中使用, 魔术方法

function __construct()
{
    函数体
}

析构函数

  • 作用: 关闭资源, 清理垃圾
  • PHP4 中没有析构函数的概念;PHP5 中才使用, 属于魔术方法

function __destruct()
{
    函数体
}

魔术方法

PHP 给某些功能预设好了函数名, 直接定义这个函数就可以实现对应的功能, 如: 随着对象的创建而加载的 __construct() 函数, 一般此类函数都是以 “__” 开头

this 指针

  • 指向成员属性: $this->属性
  • 指向成员方法: $this->方法

类的封装

  • 含义: 将属性和方法封装成一个整体, 隐藏类的内部细节
  • 步骤: 使用 private 隐藏类的属性和内部方法
  • 有关的魔术方法:

__set($proName, $proValue): 直接设置私有成员属性时调用, 可以对属性值进行限制。设置值时: $this->proName = $proValue;
__get($proName): 直接获取私有成员属性时调用。返回属性值时: return $this->proName;
__isset($proName): 使用 isset() 函数检查私有属性是否存在时调用。返回检查结果: return isset($this->proName);
__unset($proName): 使用 unset() 函数释放私有属性所占资源时调用。删除属性: unset($this->proName);

继承的作用

  • 增加开放性、可扩展性
  • 提高代码重用性
  • 提高软件可维护性
  • 继承就是用子类扩展父类
  • PHP 属于单继承

继承的应用

只要两个或以上的类中有公共部分, 就可以共享, 就能作为父类

继承的语法

  • 子类 extends 父类
  • 子类将继承父类的所有成员, 包括 private 成员, 但是子类无法直接使用父类的 private 成员

访问类型控制

  • private: 子类和外部都不能访问
  • protected: 子类能够访问, 外部不能访问
  • public: 子类和外部都能访问

子类重写父类方法

  • 子类可以声明和父类方法同名的方法, 用以覆盖父类方法
  • 如果子类中需要使用父类的方法, 不要写重复代码, 直接调用即可
  • 子类调用父类中被覆盖的方法:
  • 父类::方法名();
  • parent::方法名();
  • 子类的构造方法中尽量调用父类的方法给父类的变量初始化
  • 重写方法的访问权限不能低于父类的同名方法, 如果父类方法的访问权限是 protected, 则子类方法必须是 protected/public

PHP 中常用关键字

final

  • 作用: 使用 final 修饰的类, 不能被继承;使用 final 修饰的方法, 不能被重写
  • 注意: final 不能修饰成员属性, 只能修饰类和方法, 类中的常量是用 const 修饰

static

  • 作用: 使用 static 修饰的属性, 可以被一个类的所有对象共享;使用 static 修饰的方法, 不用创建对象就能使用
  • 注意:
  • static 只能修饰属性或方法, 不能修饰类
  • 静态数据是在类第一次被加载(第一次出现类名时)时声明, 其后都是使用
  • 静态成员必须使用类名访问: 类名::静态成员, 在 PHP5 以后可以使用 self 指代本类
  • 静态方法不能访问非静态成员, 因为可能访问时还未创建对象

const

  • 作用: 在类中定义常量属性
  • 注意:
  • 只能修饰成员属性
  • 常量不需要使用 “$”, 定义时直接是: const 常量名 = 值
  • 调用常量时需要使用 类名/self 调用
  • const 的作用域为当前命名空间;define 的作用域为全局

instanceof

可以确定一个对象是类的实例、类的子类还是实现了某个接口, 并进行相应的操作, 比较失败将退出脚本, 主要用于处理多个对象。如多个对象调用同个方法, 但是需要根据特定的对象类型调整函数的行为。


$man = new Person();
if ($man instanceof Person)
    echo '$man 是 Person 类的对象';

clone

使用 clone 关键字将创建对象副本, 而不是设置别名, 使用时自动调用 __clone() 函数


$a = new Person();
$b = clone $a;

魔术方法


__construct: 构造函数
__destruct: 析构函数
__set: 设置私有属性值时
__get: 获取私有属性值时
__isset: 判断私有属性是否存在时
__unset: 释放私有属性所占资源时
__call: 调用对象中不存在的方法时调用, 没有此方法则报错
__toString: 需要将对象转化成字符串时
__clone: 克隆出另一个副本对象(当使用 $对象2 = $对象1; 时, 只是生成别名), 在副本对象中, $this 指副本对象, $that 指原对象
__autoload: 每当使用某个类名时, 自动将类名作为参数传递给此方法, 可以在函数体内加上包含此文件的语句: include_one "./func/".$className.".class.php";
__sleep: 在序列化时自动调用, 将对象部分序列化, 不加该方法则全部序列化
__weakup: 在反序列化时自动调用

序列化和反序列化

序列化的作用是将对象长时间存储在数据库或文件中, 或者是在多个 PHP 文件中传输


序列化: serialize()
反序列化: unserialize()

抽象方法

  • 抽象方法: 没有方法体, 使用 abstract 修饰的方法
  • 抽象类
  • 类中有抽象方法, 用 abstract 修饰的类
  • 抽象类和普通类相比, 多了抽象方法和类修饰词而已
  • 抽象类不能实例化, 只有继承后实现抽象方法, 实例化才有意义
  • 除非使用了自动加载, 否则一个类必须在使用之前被定义。如果一个类扩展了另一个, 则父类必须在子类之前被声明。此规则适用于类继承其它类与接口。

接口

  • 接口是方法全为抽象方法、属性全为常量、访问权限全为 public 的抽象类, 具有抽象类的所有特征
  • 接口的类名不是使用 abstract 修饰, 而是使用 interface 修饰, 接口内的方法默认都是抽象方法, 不需要使用 abstract 修饰
  • 接口的出现是间接实现多继承, 一个类只能继承一个类, 但可以实现多个接口, 同时存在父类和接口时, 先继承后实现接口
  • 接口的实现和继承(重写了接口方法就是实现, 没有就是继承)

interface one
{
    const TAG = 'ONE';
    function f1();
}
interface two
{
    const TAG = 'TWO';
    function f2();
}
interface three extends one
{
    const TAG = 'THREE';
    function f3();
}
class Person implement one, two
{
    ...
}

关系

  • 抽象类是特殊的类, 接口是特殊的抽象类
  • 两者作用相同, 都不能创建对象, 都需要靠子类去实现方法

多态

  • 简单理解: 赋值号左右两边类型不同且具有继承关系, 就是多态
  • 多态的基础是具有继承关系的两个类中, 子类可以赋值给父类

Trait 特性

Trait 是用来混入类内使用的, 不能单独使用, 也不能实例化, 支持抽象方法、类定义静态方法、定义属性等。在类中使用 Trait 时, 相当于将 Trait 的成员拷贝到类中, 在应用时就像使用类自己的成员一样。

在类中使用 Trait


class Demo
{
    use Trait1, Trait2;
}

当两个 Trait 中具有同名方法时, 为防止歧义, 需要使用 insteadof 声明使用哪一个方法。


class Demo
{
    use Trait1, Trait2
    {
        // 声明使用 Trait1 中的 func 方法
        Trait1::func insteadof Trait2::func;
    }
}

注意事项

  • Trait 会覆盖调用类继承的父类方法
  • 从基类继承的成员被 Trait 插入的成员所覆盖。优先顺序为: 当前类的成员 > Trait 中的方法 > 被继承的方法
  • Trait 不能像类一样使用 new 实例化对象
  • 单个 Trait 可以由多个 Trait 组成
    Trait1::func insteadof Trait2::func;
    }
    }

注意事项

  • Trait 会覆盖调用类继承的父类方法
  • 从基类继承的成员被 Trait 插入的成员所覆盖。优先顺序为: 当前类的成员 > Trait 中的方法 > 被继承的方法
  • Trait 不能像类一样使用 new 实例化对象
  • 单个 Trait 可以由多个 Trait 组成
  • 在单个类中, 用 use 引入 Trait, 可以引入多个 Trait
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值