当前位置: 首页 > 知识库问答 >
问题:

如何编写遵循Liskov替代法和其他可靠原则的不可变映射,而无需代码气味?

商棋
2023-03-14

我回答了一个问题reaurding一个ImmutableMap。我建议使用代理模式。

这样做的问题是,Map包含一个put方法,它会抛出一个Un支持的操作异常。将Map的其他实例替换为ImmutableMap将打破Liskov Subsittion原则。不仅如此,还需要声明putputAll[违反了接口隔离原则]

从技术上讲,没有办法用ImmutableMap替换Map实例,因为Map只是一个接口。所以我的问题是:

由于Map包含putputAll方法,使用Map接口创建ImmutableMap会被视为破坏LSP吗?实现Map是否会被视为“具有不同接口的替代类”代码气味?如何创建遵守LSP但不包含代码气味的不可变映射

共有1个答案

太叔鹏云
2023-03-14

在我看来,ImmutableMap应该实现Map。不实现Map是个坏主意,因为有许多方法接受Map作为参数,并且只在只读意义下使用它。我不认为这违反了Liskov替代原则,因为Map的合同明确规定put是一项可选操作。

实现Map的类必须实现put,这并不理想,但另一种选择是拥有复杂的接口层次结构,每个接口只包括可能的可选方法的子集。如果有n可选方法,则必须有2^n接口来覆盖所有组合。我不知道n的值,但是有一些不明显的可选操作,例如映射返回的迭代器是否为。entrySet()。迭代器()支持setValue操作。如果将此层次结构与实际存在的接口和抽象类的层次结构相结合(包括AbstractMapSortedMapNavigableMapConcurrentNavigableMap你会弄得一团糟。

所以这个问题没有完美的答案,但是在我看来,最好的解决方案是让ImmutableMap实现Map,并确保您使用Map作为参数编写的每个方法都清楚地记录了如果传递了错误类型的Map,则必须具有Map和引发的异常

 类似资料:
  • 问题内容: 我的情况与Code Complete中Steve McConnell 提到的情况非常相似。我唯一的问题是基于车辆,而三轮车恰好是根据法律,属于汽车。到目前为止,汽车只有四个轮子。无论如何,我的域都不必要地复杂,因此很容易遵循下面的cats示例。 对重写例程并且在派生例程中不执行任何操作的类要保持怀疑。这通常表明基类的设计存在错误。例如,假设您有一个Cat类和一个例程Scratch(),

  • Liskov替代原则要求 子类型中的前提条件不能加强 任何人都可以发布一个违反上述每一点的例子和另一个解决这些问题的例子吗?

  • 我试图通过反复阅读维基百科条目来确定我对上述原则的理解。 撇开仍然让我悲伤的协变和逆变的概念不谈,wikipedia还提到超类型的不变量必须保留在子类型和历史约束或历史规则中。基于最后两个概念,我提出了一个小例子: 所以我的问题是:基于上述两个概念,我用这个例子是否违反了原则?若否,原因为何? 事先非常感谢。

  • 来自维基百科, Liskov的行为子类型概念定义了对象的可替代性概念;也就是说,如果S是T的子类型,则程序中T类型的对象可以替换为S类型的对象,而不改变该程序的任何期望属性(例如正确性)。 假设以下类层次结构: 基本抽象类-。它有一个只读属性,在后继程序中被重写。 基类的继承者-,它重写并返回灰色。 Cat的继任者-,它覆盖并返回带条纹的。 然后我们声明一个方法,参数类型为(不是)。 向该方法发送

  • 问题内容: 这是我认为不遵循应执行的代码的代码段: 如果我发表评论 该代码显然无法正常工作。如果我取消注释,那就可以了! 注意:只要按“ s”开始游戏,start就为true。但是,该方法在一开始就被调用,因此应多次无限制地显示“ hi”,直到按“ s”键为止。 图片说出一千个单词,所以我给你数百张图片(视频)来解释我的意思:https : //dl.dropbox.com/u/2792692/C

  • 我是OOP的新手。最近我读到了关于Liskov替换原理的文章。 在下面给出的代码中,Square类继承Give_区域。假设Square类与Square相关(比如有效性检查)。Give_Area给出正方形的面积(4个顶点位于圆的周长上)和圆的面积。所以,如果给我一个半径,我必须打印圆和正方形的面积(由放置在圆周长上的顶点组成)。为了得到圆的面积,我使用了一个参数。但在求平方面积时没有参数。因此,我在