java - java.util 中的堆栈类违反了 Liskov 替换原则?
问题描述
来自https://docs.oracle.com/javase/7/docs/api/java/util/Stack.html的文档
public class Stack<E> extends Vector<E>
这不是违反里氏替换原则吗?LSP 简单地说就是同一个超类的对象应该能够在不破坏任何东西的情况下相互交换。
例如:假设我有一个将 Vector 作为输入的函数。如果在调用一个函数时我开始向它传递一个堆栈,那么它可能会中断,因为堆栈阻止了元素的随机访问。
import java.util.*;
class Book {}
class TextBook extends Book {}
public class Sample {
public static void process(Vector<Book> books) {
# This should not be allowed for Stack, Stack is FILO
System.out.println(books.get(1));
}
public static void main(String[] args) {
Vector<Book> books = new Vector<>();
books.add(new Book());
books.add(new Book());
books.add(new Book());
process(books);
System.out.println("ok");
Stack<Book> bookz = new Stack();
bookz.add(new Book());
bookz.add(new Book());
bookz.add(new Book());
process(bookz);
System.out.println("ok");
}
}
解决方案
JDK 的实现Stack
是严格加法的:它只在实现中添加了少数方法,Vector's
而没有带走任何东西。出于这个原因,总是可以将 a 分配(替换)Stack
给一个类型的变量,Vector
而不限制客户端代码可以做什么。因此,这并不违反里氏替换原则。
然而,它的设计被认为是有缺陷的,但根据不同的原则:继承仅适用于子类确实是超类的子类型的情况。. 从有效的Java:
Java 平台库中有许多明显违反此原则的地方。例如,堆栈不是向量,因此 Stack 不应扩展 Vector。
推荐阅读
- sql - SQL Server:存储过程中的性能
- python - Pandas groupby 2个最近日期之间的差异
- angular - highcharts 显示不同月份的数据
- powershell - INI 文件中的 Powershell Foreach 循环
- swift - 尝试在 Mac (10.15.7) 上将 Vpn 保存到首选项但得到:Domain=NEConfigurationErrorDomain Code=10 "permission denied"
- jenkins - Jenkins 在配置 Amazon EC2 云时出错
- operating-system - 页面错误是否意味着 CPU 在页面被放入 RAM 之前被阻塞?
- plsql - 跟踪包中每个过程和函数的执行时间
- python - Python:检查一组 2D 点是否包含至少 2 条水平线
- java - 如何使用 Spring Data 从不同的表中获取附加列?