我回答了一个问题reaurding一个ImmutableMap
。我建议使用代理模式。
这样做的问题是,Map
包含一个put
方法,它会抛出一个Un支持的操作异常
。将Map
的其他实例替换为ImmutableMap
将打破Liskov Subsittion原则。不仅如此,还需要声明put
和putAll
[违反了接口隔离原则]
从技术上讲,没有办法用ImmutableMap
替换Map
实例,因为Map
只是一个接口。所以我的问题是:
由于Map
包含put
和putAll
方法,使用Map
接口创建ImmutableMap
会被视为破坏LSP吗?实现Map
是否会被视为“具有不同接口的替代类”代码气味?如何创建遵守LSP但不包含代码气味的不可变映射
?
在我看来,ImmutableMap
应该实现Map
。不实现Map
是个坏主意,因为有许多方法接受Map
作为参数,并且只在只读意义下使用它。我不认为这违反了Liskov替代原则,因为Map
的合同明确规定put
是一项可选操作。
实现Map
的类必须实现put
,这并不理想,但另一种选择是拥有复杂的接口层次结构,每个接口只包括可能的可选方法的子集。如果有n
可选方法,则必须有2^n
接口来覆盖所有组合。我不知道n
的值,但是有一些不明显的可选操作,例如映射返回的
迭代器是否为
。entrySet()。迭代器()
支持setValue
操作。如果将此层次结构与实际存在的接口和抽象类的层次结构相结合(包括AbstractMap
,SortedMap
,NavigableMap
,ConcurrentNavigableMap
,你会弄得一团糟。
所以这个问题没有完美的答案,但是在我看来,最好的解决方案是让
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个顶点位于圆的周长上)和圆的面积。所以,如果给我一个半径,我必须打印圆和正方形的面积(由放置在圆周长上的顶点组成)。为了得到圆的面积,我使用了一个参数。但在求平方面积时没有参数。因此,我在