CS61B 课程笔记(Lecture 16 Encapsulation, Lists, Delegation vs Extension)
CS61B 课程笔记(Lecture 16 Encapsulation, Lists, Delegation vs Extension)
高效编程
- 名言:“一个工程师会以十美分的代价做任何傻瓜愿意花一美元做的事。” — 保罗·希尔芬格
效率的两种含义
- 编程成本:
- 开发时间:程序的开发需要多长时间?
- 可读性与可维护性:代码的阅读、修改和维护难易程度。
 
- 执行成本(将在下周讨论):
- 执行时间:程序的执行时间。
- 内存需求:程序运行时所需的内存量。
 
本日重点
- 重点在于降低编程成本,以便快速编写代码,并减少开发过程中的挫败感。开发人员在沮丧时效率会降低。
Java中的一些有用特性
- 包:
- 优点:有助于组织代码、实现包私有性。
- 缺点:特定性强,限制了使用灵活性。
 
- 静态类型检查:
- 优点:早期发现错误,代码阅读更像故事。
- 缺点:灵活性不足,例如强制类型转换。
 
- 继承:
- 优点:可以重用代码,避免重复。
- 缺点:可能导致调试路径复杂,无法实例化抽象类或实现接口的所有方法。
 
封装
术语定义
- 模块:一组协作的方法,用于完成某个任务或相关任务。
- 封装:模块的实现完全隐藏,访问仅通过文档化的接口。
API(应用程序编程接口)
- ADT的API包含构造函数和方法的列表,以及每个方法的简要描述。
- API由语法和语义规范组成:
- 语法:编译器检查是否满足。
- 语义:测试确保功能实现正确。
 
ADT(抽象数据类型)
- ADT定义为基于行为而非实现的高层次类型。
- 例如,Proj1中的双端队列(Deque)是一个ADT,具有某些行为(如addFirst、addLast),但实现可为ArrayDeque或LinkedListDeque。
 
练习 8.1.1
任务:使用链表实现栈类,需实现push(Item x)方法,确保类是泛型的。
三种实现方式:
- 扩展(Extension): - 1 
 2
 3
 4
 5- public class ExtensionStack<Item> extends LinkedList<Item> { 
 public void push(Item x) {
 add(x); // 直接使用LinkedList的方法
 }
 }- 这种解决方案采用了扩展,借用LinkedList的方法并将其作为自己的方法。
 
- 委托(Delegation): - 1 
 2
 3
 4
 5
 6- public class DelegationStack<Item> { 
 private LinkedList<Item> L = new LinkedList<Item>();
 public void push(Item x) {
 L.add(x); // 调用LinkedList的方法
 }
 }- 委托通过创建一个LinkedList对象并调用其方法来实现目标。
 
- 适配器模式(Adapter): - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- public class StackAdapter<Item> { 
 private List<Item> L; // 使用List接口
 public StackAdapter(List<Item> worker) {
 L = worker; // 接收实现List接口的类
 }
 public void push(Item x) {
 L.add(x); // 调用List的方法
 }
 }- 此方法类似于委托,但可以使用任何实现了List接口的类(如LinkedList、ArrayList等)。
 
委托与扩展的区别
- “是一个” vs “拥有一个”:
- 一只猫有爪子(拥有一个)。
- 一只猫是一种猫科动物(是一个)。
 
- 委托:通过传入类的方法实现功能。
- 扩展:通过继承父类的方法实现功能。
视图
- 视图是现有对象的替代表示,限制用户对底层对象的访问。通过视图的更改将影响原始对象。
示例代码:
| 1 | List<String> L = new ArrayList<>(); | 
反转子列表
- 要反转部分列表的方法可通过创建一个通用反转函数来实现,因视图会修改其表示的底层对象。
- 通过子列表操作直接影响原始列表。
注意事项
- subList方法返回的是列表类型,并且通过偏移量访问原始列表的元素。
- 使用访问方法确保子列表操作对原始列表的修改。
代码示例:
| 1 | List<Item> sublist(int start, int end) { | 
- AbstractList.this用于从内部类中引用外部类的实例。
总结
- 设计API是复杂的,但保持一致的设计理念会使代码更清晰易于维护。
- 虽然继承很诱人,但应谨慎使用,仅在对类的属性有充分了解时才使用。
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 Totoroの旅!
 评论






