做Collections.unmodifiableXXX方法违反了LSP? [英] Do Collections.unmodifiableXXX methods violate LSP?

查看:274
本文介绍了做Collections.unmodifiableXXX方法违反了LSP?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Liskov替代原则 SOLID 。现在我已经读了这个原则了一些次,并试图理解它。

Liskov Substitution principle is one of the principles of SOLID. I have read this principle some number of times now and have tried to understand it.

这是我所做的,


这个原则是相关的在
级别的类之间强烈的行为契约。子类型应该能够被
超类替换,而不违反合同。

This principle is related to strong behavioral contract among the hierarchy of classes. The subtypes should be able to be replaced with supertype without violating the contract.

我已经阅读了其他一些文章,我有点迷惑了这个问题。 Do Collections.unmodifiableXXX()方法不违反LSP?

I have read some other articles too and I am a bit lost thinking about this question. Do Collections.unmodifiableXXX() methods not violate LSP?

上面链接的文章摘录:


换句话说,当通过其基类接口使用对象时,
用户只知道基础$ b的前提条件和后置条件$ b类。因此,派生对象不能指望这样的用户遵守比基础类要求更强的
前提条件



为什么我这么想?



之前

Why I think so?

Before

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

之后

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

我无法更改 SomeClass 将来会返回不可修改的列表。编译将工作,但如果客户端以某种方式尝试更改返回的 List ,那么它将在运行时失败。

I cannot change the implentation of SomeClass to return unmodifiable list in future. The compilation will work but if the client somehow tried to alter the List returned then it would fail at runtime.

这是为什么Guava为集合创建了单独的 ImmutableXXX 接口?

Is this why Guava has created separate ImmutableXXX interfaces for collections?

这是不是直接违反了LSP或者我完全错了?

Isn't this a direct violation of LSP or I have totally got it wrong?

推荐答案

LSP表示每个子类都必须遵守与超类相同的合同。是否这样就是 Collections.unmodifiableXXX()的情况,因此取决于该合同的读取方式。

LSP says that every subclass must obey the same contracts as the superclass. Wether or not this is the case for Collections.unmodifiableXXX() thus depends on how this contract reads.

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

The objects returned by Collections.unmodifiableXXX() throw an exception if one tries to call any modifying method upon them. For instance, if add() is called, an UnsupportedOperationException will be thrown.

add()的一般合同是什么?根据 API文档它是:

What is the general contract of add()? According to the API documentation it is:


确保此集合包含指定的元素(可选的
操作)。如果此集合由于
调用而更改,则返回true。 (如果此集合不允许重复,并且
已经包含指定的元素,则返回false。)

Ensures that this collection contains the specified element (optional operation). Returns true if this collection changed as a result of the call. (Returns false if this collection does not permit duplicates and already contains the specified element.)

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

If this was the full contract, then indeed the unmodifiable variant could not be used in all places where a collection can be used. However, the specification continues and also says that:


如果集合拒绝添加特定元素为任何原因
除它已经包含元素,它必须抛出
异常(而不是返回false)。这保留了
调用返回后,集合始终包含指定元素的不变

If a collection refuses to add a particular element for any reason other than that it already contains the element, it must throw an exception (rather than returning false). This preserves the invariant that a collection always contains the specified element after this call returns.

允许实现具有不将 add 的参数添加到集合中的代码,但会导致异常。当然,这包括收取客户的义务,他们认为(合法)可能性。

This explicitly allows an implementation to have code which does not add the argument of add to the collection but results in an exception. Of course this includes the obligation for the client of the collection that they take that (legal) possibility into account.

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

Thus behavioural subtyping (or the LSP) is still fulfilled. But this shows that if one plans to have different behaviours in subclasses that must also be foreseen in the specification of the toplevel class.

好的问题,由方式。

这篇关于做Collections.unmodifiableXXX方法违反了LSP?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆