Collections.unmodifierXXX 方法是否违反 LSP? [关闭]

2024-01-12

里氏替换原则 http://en.wikipedia.org/wiki/Liskov_substitution_principle是原则之一SOLID http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29。我现在已经多次阅读这个原则并试图理解它。

这是我从中得到的,

这一原则与人们之间强有力的行为契约有关。 类的层次结构。子类型应该能够替换为 超类型而不违反合同。

我读过一些其他的articles http://www.objectmentor.com/resources/articles/lsp.pdf我也是,对这个问题的思考有点迷失。做Collections.unmodifiableXXX()方法不违反LSP?

上面链接的文章摘录:

换句话说,当通过其基类接口使用对象时, 用户只知道基础的前提条件和后置条件 班级。因此,派生对象不能期望此类用户遵守 比基类所需的前提条件更强的前提条件

为什么我这么认为?

Before

class SomeClass{
      public List<Integer> list(){
           return new ArrayList<Integer>(); //this is dumb but works
      }
}

After

class SomeClass{
     public List<Integer> list(){
           return Collections.unmodifiableList(new ArrayList<Integer>()); //change in implementation
     }
}

我无法改变的实施SomeClass返回将来不可修改的列表。编译将起作用,但如果客户端尝试以某种方式改变List返回然后它会在运行时失败。

这就是 Guava 创建单独的原因吗?不可变XXX https://code.google.com/p/guava-libraries/wiki/ImmutableCollectionsExplained集合接口?

这不是直接违反LSP还是我完全搞错了?


LSP 表示每个子类都必须遵守与超类相同的契约。无论情况是否如此Collections.unmodifiableXXX()因此取决于本合同如何解读。

返回的对象Collections.unmodifiableXXX()如果尝试对它们调用任何修改方法,则会抛出异常。例如,如果add()被称为,一个UnsupportedOperationException会被抛出。

什么是总承包合同add()?根据API文档 http://docs.oracle.com/javase/1.5.0/docs/api/java/util/Collection.html#add%28E%29 it is:

确保此集合包含指定的元素(可选 手术)。如果此集合由于以下原因而发生更改,则返回 true 称呼。 (如果该集合不允许重复,则返回 false 已包含指定元素。)

如果这是完整的合同,那么确实不能在所有可以使用集合的地方使用不可修改的变体。然而,该规范继续说道:

如果集合出于任何原因拒绝添加特定元素 除了它已经包含该元素之外,它还必须抛出一个 异常(而不是返回 false)。这保留了不变性 集合始终包含在此之后的指定元素 呼叫返回。

这明确允许实现具有不添加参数的代码add到集合,但会导致异常。当然,这包括收藏品客户有义务考虑这种(合法)可能性。

因此,行为子类型(或 LSP)仍然得到满足。 但这表明,如果计划在子类中具有不同的行为,则也必须在顶级类的规范中预见到。

顺便说一句,好问题。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Collections.unmodifierXXX 方法是否违反 LSP? [关闭] 的相关文章

随机推荐

  • 是否可以直接选择 EXISTS 作为位?

    我想知道是否可以做这样的事情 这不起作用 select cast exists select from theTable where theColumn like theValue as bit 看起来应该是可行的 但是很多应该在 SQL
  • MSDeploy/WebDeploy - 通过 DacPac 部署复合数据库项目

    我们有一个数据库项目 其中的视图连接到另一个数据库中的表 另一个数据库采用不同的解决方案 在我们从其他数据库添加对 DacPac 的引用之前 此构建失败 我相信这些视图被视为 复合数据库对象 因为它们引用的对象未作为脚本包含在数据库中 而是
  • 用 C/C++ 计算 32 位 CRC 查找表

    我想计算一个 32 位 CRC 查找表 我尝试的一种方法是使用以下代码这个网站 http www barrgroup com Embedded Systems How To CRC Calculation C Code include
  • Map/Set 维护唯一的数组数组,Javascript

    我正在尝试构建唯一的数组数组 这样每当我要添加新数组时 只有在集合中尚不存在该数组时才应添加它 例如 存储 1 1 2 的所有唯一排列 实际的 1 1 2 1 2 1 1 1 2 1 2 1 2 1 1 2 1 1 预期的 1 1 2 1
  • FullCalendar.js - “获取事件时出错”

    我正在使用 FullCalendar js 显示来自多个来源的 Google 日历事件 到今天为止一直工作正常 由于某种原因 FullCalendar 开始弹出 获取事件时出错 错误消息 并且所有事件显然都消失了 这是一个jsfiddle
  • 保存到 UserDefaults 时应用程序总是崩溃

    我不知道出了什么问题 extension UserDefaults static let shared UserDefaults suiteName SharedGroupName static func set object Any fo
  • 正则表达式查找具有不同顺序的相同数字的数字

    我已经在 Google 上寻找正则表达式一个小时左右了 但似乎无法解决这个问题 如果我有电话号码 请说 2345 我想找到具有相同数字但顺序不同的任何其他数字 如下所示 2345 比如我匹配 3245 or 5432 数字相同但顺序不同 我
  • 同步数据从主存储器读取/写入

    当synchronized方法执行完成时 是只将其修改的数据推送到主存 还是所有的成员变量 同样 当synchronized方法执行时 是只从主存中读取自己需要的数据 还是清除所有的成员变量 缓存中的成员变量并从主存中读取它们的值 例如 p
  • 如何在 Tensorflow 2.0 中应用 Guided BackProp?

    我从Tensorflow 2 0并尝试实现 Guided BackProp 来显示显着性图 我首先计算之间的损失y pred and y true图像的梯度 然后找到由于这种损失而导致的所有层的梯度 with tf GradientTape
  • 在React中获取存储在Azure Blob存储中的json文件数据

    我是 React 新手 我正在尝试从存储在 Azure blob 存储中的 json 文件获取数据 file https mcbstorageprod blob core windows net exports person json 我使
  • ALSA:不支持非交错访问?

    ALSA s snd pcm hw params set access http www alsa project org alsa doc alsa lib group p c m h w params html ga4c8f1c6329
  • C# 如何将整数视为数组? [关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 假设我有 5 个整数这不是数组 我想
  • Arduino F()宏的实现

    我试图了解 Arduino 中的 F 宏实际上对 PGMEM 和 RAM 做了什么以及运行时的影响是什么 有人可以指出定义这个宏的文件吗 这可能是旧版本 但定义它的一个地方是Wstring h as in here http andybro
  • 即使 ssh 有效,Gitlab 也无法克隆存储库

    正如标题所述 即使 ssh 似乎可以工作 我也无法从 Gitlab 6 服务器克隆存储库 当尝试克隆时 它看起来像这样 git clone ssh email protected cdn cgi l email protection 133
  • 如何正确删除使用sonata-media-bundle上传的所有图像

    我已经按照建议使用 sonata media bundle 上传了一些图像here http sonata project org bundles media 2 2 doc reference usage html media new M
  • 切换按钮和开关的区别

    切换按钮和开关有什么区别 由于它们提供相同的功能 使用切换按钮或开关的具体用例是什么 切换按钮 Switch 这更多的是一个用户体验问题 而不仅仅是编码问题 这是我的回答 该控件的描述是这样说的 Toggle是一个按钮 sap m Togg
  • 为什么 go.mod 中的所有依赖都是间接的?

    我通过运行以下命令来初始化一个 go 项目 go mod init firstgo app 我确认模块已创建 cat go mod module firstgo app go 1 18 然后我通过执行安装了对 github com gin
  • 如何使用curses在终端中编写三行不断更新的行?

    我有一个程序需要输出三个不断变化的消息 连接数 已用时间和拒绝的连接 我尝试用以下方式写它们 r 在字符串末尾并在其他开始自己的输出循环之前打印换行符 认为回车符会返回一行 但它们最终都在第一行互相覆盖 我见过类似的问题 人们推荐使用cur
  • twitter bootstrap 调整手机屏幕上的文本大小

    我是 Twitter 引导程序的新手 我隐藏了一些 tr 在手机屏幕上的帮助下class hidden phone 但我想调整显示文本的大小以适合屏幕 如何在手机屏幕上调整文本大小 如下所示 span test test test test
  • Collections.unmodifierXXX 方法是否违反 LSP? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 里氏替换原则 http en wikipedia org wiki Liskov substitution principle是原则之一SOLI