第 三 章 PHP5 面 向 对 象 高 级 类 特 性 这 一 周 来 正 好 白 天 没 课, 赶 出 来 这 章 宝 宝 出 生 将 近 一 个 月, 快 10 斤 重 了 宝 宝 快 张 大, 你 想 编 程 么? 宝 宝 妈 说, 做 这 个 行 业 太 累 了 刀 客 羽 朋 于 石 家 庄 2006-11-23 1
目 录 3.1 static 变 量 方 法...3 3.1.1 静 态 属 性 公 用 特 性...4 3.1.2 静 态 属 性 直 接 调 用...5 3.1.3 静 态 方 法...6 3.1.4 静 态 方 法 如 何 调 用 静 态 方 法...7 3.1.5 静 态 方 法 调 用 静 态 属 性...8 3.1.6 静 态 方 法 不 能 调 用 非 静 态 属 性...9 3.1.6 静 态 方 法 调 用 非 静 态 方 法...10 3.1.7 设 计 模 式 之 单 件 模 式...12 3.2 final 类 final 方 法 和 常 量...16 3.2.1 final 类 的 不 能 被 继 承...16 3.2.2 final 方 法 不 能 被 重 写...17 3.2.3 PHP5 中 的 常 量...18 3.3 abstract 类 和 abstract 方 法...20 3.3.1 abstract 抽 象 类...21 3.3.2 abstract 抽 象 方 法...23 3.3.3 抽 象 类 继 承 抽 象 类...27 3.3.4 静 态 抽 象 方 法...29 3.3.5 PHP5.2.0 中 的 静 态 抽 象 方 法...30 3.4 设 计 模 式 之 模 版 模 式...31 3.4.1 模 版 模 式 实 例...31 2
3.1 static 变 量 方 法 static 关 键 字 用 来 修 饰 属 性 方 法, 称 这 些 属 性 方 法 为 静 态 属 性 静 态 方 法 static 关 键 字 声 明 一 个 属 性 或 方 法 是 和 类 相 关 的, 而 不 是 和 类 的 某 个 特 定 的 实 例 相 关, 因 此, 这 类 属 性 或 方 法 也 称 为 类 属 性 或 类 方 法 如 果 访 问 控 制 权 限 允 许, 可 不 必 创 建 该 类 对 象 而 直 接 使 用 类 名 加 两 个 冒 号 :: 调 用 static 关 键 字 可 以 用 来 修 饰 变 量 方 法 不 经 过 实 例 化, 就 可 以 直 接 访 问 类 中 static 的 属 性 和 static 的 方 法 static 的 属 性 和 方 法, 只 能 访 问 static 的 属 性 和 方 法, 不 能 类 访 问 非 静 态 的 属 性 和 方 法 因 为 静 态 属 性 和 方 法 被 创 建 时, 可 能 还 没 有 任 何 这 个 类 的 实 例 可 以 被 调 用 static 的 属 性, 在 内 存 中 只 有 一 份, 为 所 有 的 实 例 共 用 使 用 self:: 关 键 字 访 问 当 前 类 的 静 态 成 员 3
3.1.1 静 态 属 性 公 用 特 性 一 个 类 的 所 有 实 例, 共 用 类 中 的 静 态 属 性 也 就 是 说, 在 内 存 中 即 使 有 多 个 实 例, 静 态 的 属 性 也 只 有 一 份 下 面 例 子 中 的 设 置 了 一 个 计 数 器 $count 属 性, 设 置 private 和 static 修 饰 这 样, 外 界 并 不 能 直 接 访 问 $count 属 性 而 程 序 运 行 的 结 果 我 们 也 看 到 多 个 实 例 在 使 用 同 一 个 静 态 的 $count 属 性 例 3-1-1.php 4
3.1.2 静 态 属 性 直 接 调 用 静 态 属 性 不 需 要 实 例 化 就 可 以 直 接 使 用, 在 类 还 没 有 创 建 时 就 可 以 直 接 使 用 使 用 的 方 式 是 类 名 :: 静 态 属 性 名 例 3-1-2.php 类 没 有 创 建, 静 态 属 性 就 可 以 直 接 使 用 那 静 态 属 性 在 什 么 时 候 在 内 存 中 被 创 建? 在 PHP 中 没 有 看 到 相 关 的 资 料 引 用 Java 中 的 概 念, 来 解 释 应 该 也 具 有 通 用 性 静 态 属 性 和 方 法, 在 类 被 调 用 时 创 建 类 没 有 创 建, 静 态 属 性 就 可 以 直 接 使 用 那 静 态 属 性 在 什 么 时 候 在 内 存 中 被 创 建? 在 PHP 中 没 有 看 到 相 关 的 资 料 我 们 引 用 Java 中 的 概 念, 来 解 释 PHP5 的 静 态 修 饰 符, 应 该 也 具 有 通 用 性 静 态 属 性 和 方 法, 在 类 被 调 用 时 创 建 类 被 调 用, 是 指 类 被 创 建 或 者 类 中 的 任 何 静 态 成 员 被 调 用 5
3.1.3 静 态 方 法 静 态 方 法 不 需 要 所 在 类 被 实 例 化 就 可 以 直 接 使 用 使 用 的 方 式 是 类 名 :: 静 态 方 法 名 下 面 我 们 继 续 写 这 个 Math 类, 用 来 进 行 数 学 计 算 我 们 设 计 一 个 方 法 用 来 算 出 其 中 的 最 大 值 既 然 是 数 学 运 算, 我 们 也 没 有 必 要 去 实 例 化 这 个 类, 如 果 这 个 方 法 可 以 拿 过 来 就 用 就 方 便 多 了 我 们 这 只 是 为 了 演 示 static 方 法 而 设 计 的 这 个 类 在 PHP 提 供 了 max() 函 数 比 较 数 值 例 3-2-3.php 6
3.1.4 静 态 方 法 如 何 调 用 静 态 方 法 第 一 个 例 子, 一 个 静 态 方 法 调 用 其 它 静 态 方 法 时, 直 接 使 用 类 名 例 3-1-4.php 也 可 以 使 用 self:: 调 用 当 前 类 中 的 其 它 静 态 方 法 ( 建 议 ) 例 3-1-5.php 记 住 这 个 self:: 它 表 示 当 前 类 的 静 态 成 员, 与 $this 不 同,$this 指 当 前 对 象 7
3.1.5 静 态 方 法 调 用 静 态 属 性 使 用 类 名 :: 静 态 属 性 名 调 用 本 类 中 的 静 态 属 性 例 3-1-6.php 使 用 self:: 调 用 本 类 的 静 态 属 性 ( 建 议 ) 例 3-1-7.php 8
3.1.6 静 态 方 法 不 能 调 用 非 静 态 属 性 静 态 方 法 不 能 调 用 非 静 态 的 属 性 不 能 使 用 self:: 调 用 非 静 态 属 性 例 3-1-8.php 也 不 能 使 用 $this 获 取 非 静 态 属 性 的 值 例 3-1-10 9
3.1.6 静 态 方 法 调 用 非 静 态 方 法 PHP5 中, 在 静 态 方 法 中 不 能 使 用 $this 标 识 调 用 非 静 态 方 法 例 3-1-9 当 一 个 类 中 有 非 静 态 方 法 被 self:: 调 用 时, 系 统 会 自 动 将 这 个 方 法 转 换 为 静 态 方 法 下 面 的 代 码 被 执 行 了, 而 且 有 结 果 因 为 Max 方 法 被 系 统 转 换 为 静 态 方 法 了 例 :3-1-11.php 10
在 Zend Studio 的 调 试 部 分 显 示 出 了 这 些 错 误 的 信 息 下 面 的 例 子 中, 我 们 让 静 态 方 法 Max3 用 过 self:: 调 用 了 非 静 态 方 法 Max, 有 让 非 静 态 方 法 Max 通 过 $this 调 用 非 静 态 属 性 $pi 在 运 行 是 报 出 了 错 误, 这 个 错 误 和 前 一 个 例 子 3-1-9.php 一 样, 这 次 倒 是 非 静 态 方 法 Max 报 出 了 静 态 方 法 调 用 非 静 态 属 性 的 错 误 这 倒 是 证 明 了 一 点, 在 这 里 我 们 定 义 的 非 静 态 方 法 Max 被 系 统 自 动 转 换 成 静 态 方 法 了 例 :3-1-12.php 11
3.1.7 设 计 模 式 之 单 件 模 式 单 件 模 式 要 解 决 的 问 题 就 是 如 何 让 这 个 类 只 有 一 个 实 例 我 们 的 web 应 用 中, 大 量 使 用 了 数 据 库 连 接, 如 果 反 复 建 立 与 数 据 库 的 连 接 必 然 消 耗 更 多 的 系 统 资 源 我 们 如 何 解 决 这 个 问 题, 建 立 唯 一 的 数 据 库 连 接 是 必 要 的 方 式 我 们 又 如 何 知 道 与 这 个 数 据 库 的 连 接 是 否 已 经 建 立? 还 是 需 要 现 在 建 立? 单 件 模 式 可 以 解 决 这 个 问 题 先 假 设 我 们 需 要 一 个 类 完 成 在 内 存 中 只 有 一 份 的 功 能, 我 们 该 如 何 做 呢? 我 们 一 步 一 步 的 使 用 前 面 学 过 的 知 识 来 写 一 个 单 件 的 例 子 问 题 1: 前 面 学 过, 每 次 用 new 类 名 的 方 式, 就 可 以 创 建 一 个 对 象 我 们 必 须 禁 止 外 部 程 序 用 new 类 名 的 方 式 来 创 建 多 个 实 例 解 决 办 法 : 我 们 将 构 造 函 数 设 置 成 private, 让 构 造 函 数 只 能 在 内 部 被 调 用, 而 外 部 不 能 调 用 这 样, 这 个 类 就 不 能 被 外 部 用 new 的 方 式 建 立 多 个 实 例 了 例 :3-1-13.php 不 能 被 外 部 用 new 实 例 化 的 类 12
问 题 2: 我 们 已 经 禁 止 外 部 用 new 实 例 化 这 个 类, 我 们 改 如 何 让 用 户 访 问 这 个 类 呢? 前 门 堵 了, 我 们 需 要 给 用 户 留 个 后 门 解 决 办 法 : static 修 饰 的 方 法, 可 以 不 经 实 例 化 一 个 类 就 可 以 直 接 访 问 这 个 方 法 后 门 就 在 这 里 例 :3-1-14.php 13
问 题 3: 虽 然 我 们 已 经 进 入 类 内 部, 但 我 们 要 的 是 这 个 类 的 唯 一 实 例? 先 不 管 别 的, 我 们 先 需 要 一 个 实 例 通 过 这 个 static 的 方 法 返 回 这 个 实 例, 如 何 做 呢? 解 决 办 法 : private 的 构 造 函 数, 不 能 被 外 部 实 例 化 但 是 我 们 已 经 成 功 潜 入 类 的 内 部 了 ( 间 谍?007?), 我 们 在 内 部 当 然 可 以 调 用 private 的 方 法 创 建 对 象 我 们 这 样 做 看 看 例 3-1-15.php 下 面 的 例 子 我 们 确 实 返 回 了 A 类 的 实 例, 但 注 意 两 次 执 行 返 回 的 不 是 同 一 个 实 例 14
问 题 4: 我 们 已 经 通 过 static 方 法 返 回 了 A 的 实 例 但 还 有 问 题 我 们 如 何 保 证 我 们 多 次 操 作 获 得 的 是 同 一 个 实 例 的 呢? 解 决 办 法 : static 的 属 性 在 内 部 也 只 有 一 个 static 属 性 能 有 效 的 被 静 态 方 法 调 用 将 这 个 属 性 也 设 置 成 private, 以 防 止 外 部 调 用 先 将 这 个 属 性 设 置 成 null 每 次 返 回 对 象 前, 先 判 断 这 个 属 性 是 否 为 null 如 果 为 null 就 创 建 这 个 类 的 新 实 例, 并 赋 值 给 这 个 static 属 性 如 果 不 为 空, 就 返 回 这 个 指 向 实 例 的 static 属 性 例 :3-1-16.php 到 此, 我 们 写 了 一 个 最 简 单 的 单 件 模 式 现 在, 你 可 以 尝 试 写 一 个 应 用 单 件 设 计 模 式 的 数 据 库 连 接 类 要 记 住 单 件 模 式 的 使 用 效 果 和 书 写 方 式 15
3.2final 类 final 方 法 和 常 量 final--- 用 于 类 方 法 前 final 类 --- 不 可 被 继 承 final 方 法 --- 不 可 被 覆 盖 3.2.1 final 类 的 不 能 被 继 承 如 果 我 们 不 希 望 一 个 类 被 继 承, 我 们 使 用 final 来 修 饰 这 个 类 于 是 这 个 将 无 法 被 继 承 比 如 我 们 设 定 的 Math 类, 涉 及 了 我 们 要 做 的 数 学 计 算 方 法, 这 些 算 法 也 没 有 必 要 修 改,, 也 没 有 必 要 被 继 承, 我 们 把 它 设 置 成 final 类 型 例 3-2-1.php 16
3.2.2 final 方 法 不 能 被 重 写 如 果 不 希 望 类 中 的 某 个 方 法 被 子 类 重 写, 我 们 可 以 设 置 这 个 方 法 为 final 方 法, 只 需 要 在 这 个 方 法 前 加 上 final 修 饰 符 如 果 这 个 方 法 被 子 类 重 写, 将 会 出 现 错 误 例 :3-2-1.php 17
3.2.3 PHP5 中 的 常 量 在 PHP5 类 中 继 续 使 用 cons 修 饰 常 量 我 们 使 用 const 定 义 一 个 常 量, 定 义 的 这 个 常 量 不 能 被 改 变 在 PHP5 中 const 定 义 的 常 量 与 定 义 变 量 的 方 法 不 同, 不 需 要 加 $ 修 饰 符 const PI = 3.14; 这 样 就 可 以 而 使 用 const 定 义 的 常 量 名 称 一 般 都 大 写, 这 是 一 个 约 定, 在 任 何 语 言 中 都 是 这 样 如 果 定 义 的 常 量 由 多 个 单 词 组 成, 使 用 _ 连 接, 这 也 是 约 定 比 如, MAX_MUMBER 这 样 的 命 名 方 式 一 个 良 好 的 命 名 方 式, 是 程 序 员 必 须 注 意 的 类 中 的 常 量 使 用 起 来 类 似 静 态 变 量, 不 同 点 只 是 它 的 值 不 能 被 改 变 我 们 使 用 类 名 :: 常 量 名 来 调 用 这 个 常 量 例 3-2-3.php 18
尝 试 为 const 定 义 的 常 量 赋 值, 将 会 出 现 错 误 例 3-2-4.php 19
3.3 abstract 类 和 abstract 方 法 可 以 使 用 abstract 来 修 饰 一 个 类 或 者 方 法 用 abstract 修 饰 的 类 表 示 这 个 类 是 一 个 抽 象 类, 用 abstract 修 饰 的 方 法 表 示 这 个 方 法 是 一 个 抽 象 方 法 抽 象 类 不 能 被 实 例 化 抽 象 方 法 是 只 有 方 法 声 明, 而 没 有 方 法 的 实 现 内 容 20
3.3.1 abstract 抽 象 类 可 以 使 用 abstract 来 修 饰 一 个 类 用 abstract 修 饰 的 类 表 示 这 个 类 是 一 个 抽 象 类 抽 象 类 不 能 被 实 例 化 这 是 一 个 简 单 抽 象 的 方 法, 如 果 它 被 直 接 实 例 化, 系 统 会 报 错 例 :3-3-1.php 21
例 :3-3-2.php 下 面 例 子 的 NormalUser 继 承 自 User 类, 就 可 以 被 实 例 化 了 单 独 设 置 一 个 抽 象 类 是 没 有 意 义 的, 只 有 有 了 抽 象 方 法, 抽 象 类 才 有 了 血 肉 下 面 介 绍 抽 象 方 法 22
3.3.2 abstract 抽 象 方 法 用 abstract 修 饰 的 类 表 示 这 个 方 法 是 一 个 抽 象 方 法 抽 象 方 法, 只 有 方 法 的 声 明 部 分, 没 有 方 法 体 抽 象 方 法 没 有 {}, 而 采 用 ; 结 束 一 个 类 中, 只 要 有 一 个 抽 象 方 法, 这 个 类 必 须 被 声 明 为 抽 象 类 抽 象 方 法 在 子 类 中 必 须 被 重 写 下 面 是 一 个 抽 象 类, 其 中 有 两 个 抽 象 方 法, 分 别 是 setsal() 和 getsal() 用 来 取 回 $sal 员 工 的 工 资 例 :3-3-3.php 23
既 然 User 类 不 能 被 直 接 继 承, 我 们 写 一 个 NormalUser 类 继 承 自 User 类 当 我 们 写 成 如 下 代 码 时, 系 统 会 报 错 这 个 错 误 告 诉 我 们, 在 User 类 中 有 两 个 抽 象 方 法, 我 们 必 须 在 子 类 中 重 写 这 两 个 方 法 例 :3-3-4.php 例 :3-3-5.php 下 面 例 子, 重 写 了 这 两 个 方 法, 虽 然 方 法 体 里 面 {} 的 内 容 是 空 的, 也 算 重 写 了 这 个 方 法 注 意 看 重 写 方 法 的 参 数 名 称, 这 里 只 要 参 数 数 量 一 致 就 可 以, 不 要 求 参 数 的 名 称 必 须 一 致 24
下 面 19-21 行, 三 种 写 重 写 的 方 式 都 会 报 错 19 行, 缺 少 参 数 20 行, 参 数 又 多 了 21 行, 参 数 类 型 不 对 ( 这 种 写 法 在 以 后 章 节 介 绍 ) 例 :3-3-3.php 25
一 个 类 中, 如 果 有 一 个 抽 象 方 法, 这 个 类 必 须 被 声 明 为 抽 象 类 下 面 这 个 类 不 是 抽 象 类, 其 中 定 义 了 一 个 抽 象 方 法, 会 报 错 例 :3-3-7.php 26
3.3.3 抽 象 类 继 承 抽 象 类 抽 象 类 继 承 另 外 一 个 抽 象 类 时, 不 用 重 写 其 中 的 抽 象 方 法 抽 象 类 中, 不 能 重 写 抽 象 父 类 的 抽 象 方 法 这 样 的 用 法, 可 以 理 解 为 对 抽 象 类 的 扩 展 下 面 的 例 子, 演 示 了 一 个 抽 象 类 继 承 自 另 外 一 个 抽 象 类 时, 不 需 要 重 写 其 中 的 抽 象 方 法 例 :3-3-8.php 27
抽 象 类 在 被 继 承 后, 其 中 的 抽 象 方 法 不 能 被 重 写 如 果 发 生 重 写, 系 统 会 报 错 例 3-3-9.php 抽 象 类 继 承 抽 象 类, 目 的 对 抽 象 类 的 扩 展 例 3-3-10.php 28
3.3.4 静 态 抽 象 方 法 在 PHP5.1 中, 抽 象 类 中 支 持 静 态 抽 象 方 法 下 面 这 个 例 子, 看 到 静 态 抽 象 方 法 可 以 声 明 实 现 这 个 方 法 时, 必 须 是 静 态 的 方 法 例 :3-3-11.php 29
3.3.5 PHP5.2.0 中 的 静 态 抽 象 方 法 在 PHP5.2.0 的 更 新 信 息 中 有 这 样 一 段 话 : 译 文 :( 因 为 疏 漏, 在 PHP5.0 和 PHP5.1 的 类 中 允 许 静 态 抽 象 方 法 在 PHP5.2 中, 只 有 接 口 可 以 拥 有 静 态 抽 象 方 法 ) 在 PHP5.2.0 版 本 中 测 试, 刚 才 的 代 码 执 行 正 常 在 PHP5.2.0 中 是 依 然 兼 容 30
3.4 设 计 模 式 之 模 版 模 式 抽 象 类 的 应 用 就 是 典 型 的 模 版 模 式, 先 声 明 一 个 不 能 被 实 例 化 的 模 版, 在 子 类 中 去 依 照 模 版 实 现 具 体 的 应 用 3.4.1 模 版 模 式 实 例 我 们 写 这 样 一 个 应 用 : 银 行 计 算 利 息, 都 是 利 率 乘 以 本 金 和 存 款 时 间, 但 各 种 存 款 方 式 计 算 利 率 的 方 式 不 同, 所 以, 在 账 户 这 个 类 的 相 关 方 法 里, 只 搭 出 算 法 的 骨 架, 但 不 具 体 实 现 具 体 实 现 由 各 个 子 类 来 完 成 例 :LoanAccount.php 以 后, 所 有 和 计 算 利 息 的 类 都 继 承 自 这 个 类, 而 且 必 须 实 现 其 中 的 getinterestrate() 方 法, 这 种 用 法 就 是 模 版 模 式 下 一 章 将 介 绍 面 向 对 象 语 言 的 其 它 重 要 组 成 接 口 多 态 31