矩形和框类中的equals()方法

时间:2013-03-20 04:39:46

标签: java

我有一个类层次结构,如下所示......

public class Rectangle2
{
    // instance variables 
    private int length;
    private int width;
    /**
     * Constructor for objects of class rectangle
     */
    public Rectangle2(int l, int w)
    {
        // initialise instance variables
        length = l;
        width = w;
    }
    // return the height
    public int getLength()
    {
        return length;
    }
    public int getWidth()
    {
        return width;
    }
    public String toString()
    {
        return "Rectangle - " + length + " X " + width;
    }
}

public class Box2 extends Rectangle2
{
    // instance variables 
    private int height;
    /**
     * Constructor for objects of class box
     */
    public Box2(int l, int w, int h)
    {
        // call superclass
        super(l, w);
        // initialise instance variables
        height = h;
    }
    // return the height
    public int getHeight()
    {
        return height;
    }
    public String toString()
    {
        return "Box - " + getLength() + " X " + getWidth() + " X " + height;
    }
}

public class Cube extends Box2 {
            public Cube(int length)
             {
              super(length, length, length);
             } 
            public String toString()
    {
        return "Cube - " + getLength() + " X " + getWidth() + " X " + getHeight();
    }
}

我想在所有类中添加一个equals()方法,这样如果一个类的输出等于其他类输出,它将打印“Box和Cube具有相同的维度”。我真的很困惑。我所知道的是,我必须使用if-else声明,但之后我就想不出该做什么。

这是我的问题所要做的: 3.还要为类添加equals()方法,以便根据其维度的值确定两个矩形,框或多维数据集何时相等。 Cube应该继承Box类的equals方法而不是覆盖它。 这是输出应该是这样的: http://i.stack.imgur.com/Kgti1.png

2 个答案:

答案 0 :(得分:2)

这是一个坏主意,但您可以在equals中定义Box2,如下所示:

public class Box2 extends Rectangle2 {
  //...

  boolean equals(Object o) {
   //a quick check if we are comparing with ourselves
   if (this==o) return true; 

   //no object is equals to null
   if (o==null) return false;

   //compare only if o is an instance of Box
   if (o instanceof Box2) {
     (Box2) that = (Box2) o;
     if (this.getWidth()!=that.getWidth()) return false;
     if (this.getLength()!=that.getLength()) return false;
     if (this.getHeight()!=that.getHeight()) return false;
     return true;
   }

   //instances of other classes cannot be equal to this instance
   return false;
  }

}

由于Cube延伸equals,所以具有相同尺寸的任何Box将等于具有相同尺寸的另一个框。 CubeBox

为什么这是一个坏主意?假设我们有一个扩展BoxWithColor的类Box并添加一个表示框颜色的变量

public class BoxWithColor extends Box {
  public String color;
  public BoxWithColor(String color, int l, int w, int h) {
    super(l,w,h);
    this.color=color;
  }      
}

现在new BoxWithColor("red",1,2,3).equals(new Box(1,2,3)),这是错误的。

通常,应为同一类实例保留equals。

答案 1 :(得分:1)

以下是如何做到这一点:

public class Rectangle {

    private final int length;
    private final int width;

    public Rectangle(int length, int width) {
        this.length = length;
        this.width = width;
    }

    public int getLength() {
        return length;
    }

    public int getWidth() {
        return width;
    }

    public String toString() {
        return "Rectangle - " + length + " X " + width;
    }

    @Override
    public int hashCode() {
        return (length * 159) + (width * 523);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Rectangle)) {
            return false;
        }
        Rectangle that = (Rectangle) obj;
        return this.hashCode() == that.hashCode();
    }

}

覆盖equals时需要覆盖hashCode,因为contract of hashCode表示如果对象相等,hashCode必须相同。 hashCode的实现应尽量避免为不同的对象生成相同的hashCode,但这不是一个硬性要求。因此,这里显示的方法就足够了。 hashCode主要用于在使用像HashMap这样的bucketing系统的数据结构中很好地分配对象,因此对于这种数据结构的性能,如果hashCodes具有良好的传播,它将非常有用。

    public class Box extends Rectangle {

    private final int height;

    public Box(int length, int width, int height) {
        super(length, width);
        this.height = height;
    }

    public int getHeight() {
        return height;
    }

    public String toString() {
        return "Box - " + getLength() + " X " + getWidth() + " X " + height;
    }

    @Override
    public int hashCode() {
        return super.hashCode() + (height * 343);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) {
            return true;
        }
        if (!(obj instanceof Box)) {
            return false;
        }
        Box that = (Box) obj;
        return this.hashCode() == that.hashCode();
    }
}

Box可以调用super.hashCode()并为额外参数' height'添加一个因子。请注意,使用此方法,高度为零的框将具有与具有相同长度和宽度的Rectangle相同的hashCode。这不是必要条件,但在某些条件下可能有用。

public class Cube extends Box {

    public Cube(int length) {
        super(length, length, length);
    }

    public String toString() {
        return "Cube - " + getLength() + " X " + getWidth() + " X "
                + getHeight();
    }
}

Cube可以在Rectangle和Box中完成的工作中徒步。这一切都很好的原因是所有这些类中的字段都是不可变的(例如,没有setter)。我强调了这一点,因为它们都是最终的,因此编译器确实无法更改它们。如果您有setter,则可以创建一个多维数据集,然后将宽度设置为不同的值。这会搞砸这种设计。有关详细信息,请参阅文章'A Square Is Not A Rectangle'