Menu
CoddyTech

信息隐藏

本课属于 Coddy PHP 学习旅程的“面向对象编程”单元。第 41 课,共 91 课。

信息隐藏是封装背后的原则,也就是类应该只公开必要的内容,并隐藏其内部实现细节。访问修饰符和 getter/setter 是实现这一原则的工具,而信息隐藏则是指导你如何使用这些工具的设计理念。

目标是明确区分类做什么(它的公共接口)和它如何实现(它的内部实现)。这样分离后,你可以更改内部实现,而不影响使用该类的代码:

<?php
class Temperature {
    private float $celsius;
    
    public function setCelsius(float $value): void {
        $this->celsius = $value;
    }
    
    public function getCelsius(): float {
        return $this->celsius;
    }
    
    public function getFahrenheit(): float {
        return ($this->celsius * 9/5) + 32;
    }
}

$temp = new Temperature();
$temp->setCelsius(25);
echo $temp->getCelsius() . "C = " . $temp->getFahrenheit() . "F";

输出:

25C = 77F

这个类在内部以摄氏度存储温度,但用户不需要知道这一点。以后你可以将内部存储改为华氏度或开尔文,只要公共方法的使用方式保持不变,外部代码就不会出问题。

关键点:信息隐藏可以保护你的代码免受变化的影响。隐藏实现细节,只公开稳定的接口,这样你的类就会更易于维护和修改。

challenge icon

挑战

简单

让我们构建一个货币转换器,演示信息隐藏的实际应用。你将创建一个类,在内部以一种货币存储金额,同时能够轻松地转换多种货币,外部代码完全不需要知道数据实际上是如何存储的。

你将把代码分成两个文件:

  • Money.php:创建一个 Money 类,在内部将所有金额存储为分(整数),以避免浮点精度问题。这个实现细节应对类的使用者完全隐藏。这个类应提供:
    • 一个用于存储分金额的私有属性
    • setDollars(float $amount):接受美元金额,并在内部将其存储为分
    • getDollars():以美元形式返回金额(浮点数,保留 2 位小数)
    • setEuros(float $amount):接受欧元,并按汇率 1 EUR = 1.10 USD 转换为分
    • getEuros():返回转换为欧元后的金额(浮点数,保留 2 位小数)
    • getInternalValue():返回原始的分值(整数),用于调试
  • main.php:引入 Money 文件。你会收到两个输入:美元金额和欧元金额。创建一个 Money 实例。首先,设置美元金额(转换为浮点数),并打印三行:美元金额、对应的欧元金额,以及内部的分值。然后,设置欧元金额(转换为浮点数),并再次打印相同的三个值。

这种设计的优点是,外部代码使用熟悉的美元和欧元金额,却完全不知道所有金额在内部都以分存储。之后你可以改用其他基础货币或不同的精度策略来进行内部存储,只要公共方法仍能正常工作,外部代码就不需要做任何更改。

美元和欧元金额都必须格式化为恰好保留 2 位小数。每个值都应单独占一行,总共输出六行。

亲手试试

<?php

require_once 'Money.php';

// 读取输入
$dollarAmount = floatval(trim(fgets(STDIN)));
$euroAmount = floatval(trim(fgets(STDIN)));

// TODO:创建一个 Money 实例

// TODO:设置美元金额并打印:
// 美元值(保留 2 位小数)
// 等值欧元金额(保留 2 位小数)
// 内部的美分值(整数)

// TODO:设置欧元金额并打印:
// 美元值(保留 2 位小数)
// 等值欧元金额(保留 2 位小数)
// 内部的美分值(整数)

?>
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: PHP 在线编译器