Joshua Blotch的《有效Java》中写道:
除非您愿意放弃面向对象抽象的好处,否则在保留等于
契约的同时,无法扩展可实例化类并添加值组件。
有效Java给出了一些例子,这些例子要么破坏了对称性、传递性,要么破坏了Liskov替换原理<我想你已经读过了。我觉得我不应该把整个项目都贴在这里
点
:
public class Point{
private final int x;
private final int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
protected boolean equalsImpl(Point p){
return p.x == x && p.y == y;
}
@Override
public final boolean equals(Object o) {
if(!(o instanceof Point))
return false;
Point p = (Point)o;
return equalsImpl(p) && p.equalsImpl(this);
}
// Remainder omitted ...
}
ColPoint
:
public class ColorPoint extends Point{
private java.awt.Color color;
public ColorPoint(int x, int y, java.awt.Color color){
super(x, y);
this.color = color;
}
@Override
protected boolean equalsImpl(Point p){
return (p instanceof ColorPoint) &&
super.equalsImpl(p) &&
((ColorPoint)p).color == color;
}
// Remainder omitted ...
}
我知道在这种情况下应该使用合成,但是我想知道我的解决方案是否真的遵守
equals
契约。如果是,有效Java的陈述是错误的吗?
我想知道什么是LSP,所以我偶然发现了一篇好文章。正如文章所说,Liskov Substution原则不适用于Java
LSP对属性集定义了一个弱约束,但随后声称,对于任何属性,都可以证明程序行为是相同的。唯一可以验证这一点的方法是,如果系统中的原始对象由其规范严格定义,以至于它们不允许其他实现。例如,上述论文的作者声称,给定一个方法的一组属性,他们可以声称与另一个具有相同契约的方法在行为上100%兼容——但这不是真的。本质上,我可以说Java中toString()方法的约定非常弱——“返回对象的字符串表示”。
为什么Liskov替换原则很重要?
参考链接,可能会澄清您的疑问。
equals
合约不需要LSP。
也许这个问题是因为在等于
实现的主题中不必要地包含了LSP。eclipse生成的标准equals
实现已经使用了super。等于
(利用继承),并且比建议的解决方案更正确、更简单。然而,它不符合LSP的标准,根据文件,LSP是可以的。
匿名用户
在这种实现中,任何色点
都不等于点
,因此它违反了Liskov替换原则。不过,它确实尊重与同等的合同。
更新:LSP是否被破坏取决于Point
类具有的契约。如果您有一个契约说“具有相同X和Y坐标的两个点相等”或“您可以使用HashSet
来消除具有重复坐标的点”,它就被破坏了。如果不存在这样的合同,LSP就不会违约。
另一方面,如果没有色点
等于点
,那么色点
是-a点
有意义吗?
根据Joshua Blotch的有效Java: 除非您愿意放弃面向对象抽象的好处,否则在保留compareTo契约的同时,无法使用新的值组件扩展可实例化类 你能用例子和挑战来解释以上内容吗?你能解释一下Joshua所说的“价值成分”是什么意思,以及还有哪些其他类型的成分可用吗。 这使您可以在第二类上实现您喜欢的任何方法,同时允许其客户端在需要时将第二类的实例视为第一类的实例。 你能解释一下约书亚所
本文向大家介绍C#实现Array添加扩展实例,包括了C#实现Array添加扩展实例的使用技巧和注意事项,需要的朋友参考一下 一般学过C#的都知道,Array 一旦定义好,比如四个长度,当需要再往里面添加元素的时候,需要Array.Resize一下才可以。有鉴于此,为了提高代码复用,所以索性封装下,方便使用。 具体实现代码如下: 测试代码: 测试结果: 代码逻辑很简单,无需说明,只是方面后续使用而已
从activity_main.xml和ClassNotFoundException中删除。我在谷歌上搜索了一下,看看在Android中扩展EditText。我做错了什么?以及扩展EditText以赋予它额外的“默认”功能的正确方法。 我花了几个小时看自己却看不见,谁能看出我哪里出了问题吗。
问题内容: 我正在寻找与C#扩展方法功能等效的Java。现在,我一直在阅读有关Java 8的默认方法的信息,但据我所知,我只能将它们添加到接口中。 …是否有任何语言功能可让我为未实现接口的最终类编写扩展方法?(我宁愿不必包装它…) 问题答案: 对于以扩展类型作为第一个参数的静态方法,C#扩展方法只是语法糖。Java默认方法完全不同。要模仿C#扩展方法,只需编写常用的静态方法。但是,您将不会食用
我想将两个哈希数组合并到一个新数组中: 现在这就是我正在寻找的结果: 我在Ruby文档中唯一能找到的合并选项是用另一个散列覆盖重复项。那么如何才能达到我需要的版本呢?
问题内容: 我是这些泛型类型的新手。在下面的代码中,我创建了一个方法,该方法接受扩展了“字符串”的项目列表。 我的问题?-当列表可以分配一个新列表时,为什么不能添加字符串“ test” …这给了我一个编译错误。 问题答案: 因为与此处无关的不是运行时类型。仍然是类型,您刚巧将其分配给。考虑一下: 编译器无法确定其是否有效-它仅基于的编译时类型进行决策。 请注意,实际上没有任何扩展,这是一个类。