资讯专栏INFORMATION COLUMN

复合优先于继承(重写equals方法引出的建议)

villainhr / 2111人阅读

摘要:即不使用继承方式,而将父类包含在子类中重写只有当坐标和颜色都相同才返回当然,重写的时候一定记得重写重写重写参考文献第二版第条覆盖方法时请遵守通用约定

问题复现:
首先有一个Point类,重写了equals方法:

public class Point{
    private final int x;
    private final int y;
    public Point(x,y){
        this.x=x;
        this.y=y;
    }
    @Override public boolean queals(Object o){
        if(!(o instanceof Point){
            return false;
        }
        Point p = (Point)o;
        return p.x == x && p.y == y;
    }
}

另有一个扩展类,ColorPoint继承Point类

public class ColorPoint{
    private final Color color;
    public ColorPoint(int x,int y,Color color){
        super(x,y);
        this.color=color;
    }
}

这时候比较两个点的时候就有个问题:

Point point = new Point(1, 2);
ColorPoint cPoint = new ColorPoint(1, 2, Color.RED);
System.out.println(point.equals(cPoint)); // true
System.out.println(cPoint.equals(point); // false

可以发现equals方法违背了对称性原则,原因是Point的equals方法在接收ColorPoint类型的参数时,会将其当做Point进行比较,忽略了颜色的判断,认定两个类是相等的。
对此我们做出一些修改:

此时可修改equals方法,加入对颜色的判断:
if(!(o.instanceOf(Point))
    return false;
//if o is a normal point,ignore color
if(!(o.instanceOf(ColorPoint))
    return o.equals(this);
//if o is a colorPoint .do a full compation
return super.equals(o) && ((ColorPoint)o).equals(this.color);

这段代码修复了违背对称性的错误,但两个以上的点会有错误,比如 两个ColorPoint和一个Point作比较,如下:

ColorPoint cPointRed = new ColorPoint(1, 2, Color.RED);
Point point = new Point(1, 2);
ColorPoint cPointBlue = new ColorPoint(1, 2, Color.BLUE);
System.out.println(cPointRed.equals(point)); // true
System.out.println(point.equals(cPointBlue)); // true
System.out.println(cPointRed.equals(cPointBlue)); // false

这样又违背了传递性原则。这时候就有个建议:复合优先于继承
即不使用继承方式,而将"父类"包含在"子类"中

public class ColorPoint{
    private final Point point;
    private final Color color;
    public ColorPoint(int x,int y,Color color){
        point.x = x;
        point.x = x
        this.color = color;
    }
    public Point getPoint(){
        return this.point;
    }
    //重写equals
    @Override public boolean equals(Object o){
        if(!(o instanceof ColorPoint){
            return false;
        }
        ColorPoint cp = (ColorPoint)o;
        //只有当坐标和颜色都相同才返回true;
        return cp.point.equals(this.point) && cp.Color.equals(color);
    }
}

当然,重写equals的时候一定记得重写hashCode~重写hashCode~重写hashCode~~de~de~de~

参考文献:《Effective Java》第二版 第8条 “覆盖equals方法时请遵守通用约定”

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76881.html

相关文章

  • Effective Java 第三版 全文翻译

    摘要:本章中的大部分内容适用于构造函数和方法。第项其他方法优先于序列化第项谨慎地实现接口第项考虑使用自定义的序列化形式第项保护性地编写方法第项对于实例控制,枚举类型优先于第项考虑用序列化代理代替序列化实例附录与第版中项目的对应关系参考文献 effective-java-third-edition 介绍 Effective Java 第三版全文翻译,纯属个人业余翻译,不合理的地方,望指正,感激...

    galois 评论0 收藏0
  • Effective Java 3rd.Edition 翻译

    摘要:推荐序前言致谢第一章引言第二章创建和销毁对象第项用静态工厂方法代替构造器第项遇到多个构造器参数时要考虑使用构建器第项用私有构造器或者枚举类型强化属性第项通过私有构造器强化不可实例化的能力第项优先考虑依赖注入来引用资源第项避免创建不必要的对象 推荐序 前言 致谢 第一章 引言 第二章 创建和销毁对象 第1项:用静态工厂方法代替构造器 第2项:遇到多个构造器参数时要考虑使用构建器 第...

    KoreyLee 评论0 收藏0
  • CSS学习摘要-层叠和继承

    摘要:类选择器具有更高的专用性,所以将战胜元素选择器。个位在整个选择器中每包含一个元素选择器或伪元素就在该列中加分。选择器六明显地输给了了五,其专用性值为和它在链中少了一个元素选择器。当有多个选择器作用在一个元素上时,哪个规则最终会应用到元素上? 其实这是通过层叠机制来控制的,这也和样式继承(元素从其父元素那里获得属性值)有关。 元素的最终样式可以在多个地方定义,它们以复杂的形式相互影响。这些复杂...

    mating 评论0 收藏0
  • 不知道层叠,别说你懂CSS

    摘要:知道存在是很有用的,这样当你在别人的代码中遇到它时,你就知道它是什么了。如上面所示的示例所示,元素选择器具有很低的特殊性。类选择器具有更高特殊性,所以将战胜元素选择器。个位在整个选择器中每包含一个元素选择器或伪元素就在该列中加分。 在实际的工作中,我们可能还有些疑惑,当有多个选择器作用在一个元素上时,哪个规则最终会应用到元素上?其实这是通过层叠机制来控制的,这也和样式继承(元素从其父元...

    izhuhaodev 评论0 收藏0
  • Java 高效编程(Effective Java)中文第三版

    摘要:来源前条来源一书英文版已经出版,这本书的第二版想必很多人都读过,号称四大名著之一,不过第二版年出版,到现在已经将近年的时间,但随着,,,甚至的发布,语言发生了深刻的变化。译者在这里第一时间翻译成中文版。供大家学习分享之用。 来源:sjsdfg/effective-java-3rd-chinese前 51 条来源:Effective Java, Third Edition 《Effec...

    ysl_unh 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<