Menu
CoddyTech

信息隐藏

本课属于 Coddy Dart 学习旅程的“面向对象编程”单元。第 34 课,共 110 课。

信息隐藏是封装背后的原则,也就是说,类应该隐藏其内部工作原理,只公开必要的内容。你已经学习了相关机制(私有字段、获取器、设置器),但真正的目标是设计出易于使用且不易被误用的类。

考虑一个用于管理用户密码的类。内部存储和哈希逻辑应完全隐藏:

class UserAccount {
  String _username;
  String _passwordHash;
  
  UserAccount(this._username, String password) 
      : _passwordHash = _hashPassword(password);
  
  static String _hashPassword(String password) {
    return 'hashed_$password';  // 简化示例
  }
  
  bool verifyPassword(String password) {
    return _passwordHash == _hashPassword(password);
  }
  
  String get username => _username;
}

外部代码看不到密码哈希,也不知道它是如何存储的。它们只需调用 verifyPassword()。这种分离意味着你可以彻底更改哈希算法,而不会影响任何使用这个类的代码。

关键在于从外部向内思考你的类。

问问自己:“使用这个类的人实际需要什么?”只公开这些内容,其他内容都设为私有。这样就能明确区分类的功能(它的公共接口)和实现方式(它的私有实现)。

challenge icon

挑战

简单

让我们构建一个安全的钱包系统,展示信息隐藏的实际应用。你将创建一个数字钱包,用于管理用户的余额和交易历史,并将所有敏感的内部细节完全隐藏起来,不让外部代码访问。

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

  • wallet.dart:创建一个 Wallet 类,安全地管理资金。钱包应公开存储所有者的姓名,但其他所有内容都应通过简洁的公共接口隐藏起来:
    • 内部余额和交易记录应设为私有,外部代码不应看到你如何存储或跟踪资金
    • 使用一个私有方法在内部记录交易(存储类似 "Deposit: $50.0" 或 "Withdrawal: $30.0" 这样的条目)
    • 提供一个公共的 deposit(double amount) 方法,用于存入资金(仅当金额为正数时),并在内部记录交易
    • 提供一个公共的 withdraw(double amount) 方法,仅当资金充足且金额为正数时才取出资金,并在内部记录交易。成功时返回 true,否则返回 false
    • 提供一个公共 getter balance,用于返回当前余额(只读访问)
    • 提供一个公共方法 getTransactionCount(),用于返回已记录的交易数量(不公开实际的交易列表)
    • 提供一个公共方法 getLastTransaction(),用于返回最近一笔交易的字符串;如果没有交易,则返回 "No transactions"
    • 添加一个 printSummary() 方法,用于显示钱包状态
  • main.dart:导入钱包,并演示信息隐藏如何创建简洁、安全的接口:
    • 为所有者 "Sarah" 创建一个钱包
    • 存入 100.0
    • 存入 50.0
    • 尝试取出 200.0,并根据结果打印 "Withdrawal of 200.0: [success/failed]"
    • 取出 30.0,并打印 "Withdrawal of 30.0: [success/failed]"
    • 调用 printSummary()
    • 打印 "Transaction count: [count]"
    • 打印 "Last transaction: [transaction]"

printSummary() 方法应打印:

=== Wallet Summary ===
Owner: [ownerName]
Balance: $[balance]

注意,外部代码可以通过清晰、明确的方法与钱包交互,而完全不必了解余额是如何存储的,或交易是如何在内部跟踪的。实现细节会被完全隐藏起来。你可以更改交易的存储方式,而不会影响任何使用该钱包的代码。

预期输出:

Withdrawal of 200.0: failed
Withdrawal of 30.0: success
=== Wallet Summary ===
Owner: Sarah
Balance: $120.0
Transaction count: 3
Last transaction: Withdrawal: $30.0

亲手试试

import 'wallet.dart';

void main() {
  // TODO:为所有者 "Sarah" 创建一个钱包
  
  // TODO:存入 100.0
  
  // TODO:存入 50.0
  
  // TODO:尝试取出 200.0,并打印结果
  // 格式:"Withdrawal of 200.0: [success/failed]"
  
  // TODO:取出 30.0,并打印结果
  // 格式:"Withdrawal of 30.0: [success/failed]"
  
  // TODO:调用 printSummary()
  
  // TODO:打印交易笔数
  // 格式:"Transaction count: [count]"
  
  // TODO:打印最后一笔交易
  // 格式:"Last transaction: [transaction]"
}
quiz icon自我测试

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

面向对象编程中的所有课

自己练习: Dart 在线编译器