-2

以下に示すクラス階層があります...

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() メソッドをすべてのクラスに追加して、あるクラスの出力が他のクラスの出力と等しい場合に「ボックスとキューブは同じ次元を持っています」と出力するようにします。私は本当に混乱しています。私が知っているのは、if-elseステートメントを使用する必要があるということだけですが、その後はどうすればよいかわかりません。

これが私の質問の内容です: 3. クラスに equals() メソッドを追加して、2 つの Rectangle、Box、または Cube がそれらの寸法の値に基づいていつ等しいかを判断できるようにします。Cube は、Box クラスの equals メソッドをオーバーライドするのではなく、継承する必要があります。出力は次のようになります: http://i.stack.imgur.com/Kgti1.png

4

2 に答える 2

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のボックスは、同じ寸法の別のボックスと等しくなります。ACubeBoxです。

なぜそれは悪い考えですか?ボックスの色を表す変数を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は同じクラスのインスタンス用に予約する必要があります。

于 2013-03-20T04:49:49.503 に答える
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();
    }

}

等しいをオーバーライドする場合は、hashCodeをオーバーライドする必要があります。これは、hashCodeのコントラクトでは、オブジェクトが等しい場合はhashCodeが同じである必要があると規定されているためです。hashCodeの実装は、異なるオブジェクトに対して同じhashCodeを生成しないようにする必要がありますが、これは難しい要件ではありません。したがって、ここに示すようなアプローチで十分です。hashCodeは主に、HashMapなどのバケットシステムを使用するデータ構造でオブジェクトを適切に分散するために使用されるため、このようなデータ構造のパフォーマンスには、hashCodeが適切に分散されていると便利です。

    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'の係数を追加できます。このアプローチでは、高さがゼロのボックスは、同じ長さと幅の長方形と同じ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で行われた作業に沿ってハイキングすることができます。これがすべてうまく機能する理由は、これらすべてのクラスのフィールドが不変であるためです(たとえば、セッターがありません)。私はそれらをすべて最終的なものにすることでこれを強調したので、コンパイラーはそれらが変更されないことを本当に確認します。セッターがいる場合は、立方体を作成してから、幅を別の値に設定できます。これはこの設計を台無しにするでしょう。詳細については、記事「正方形は長方形ではありません」を参照してください。

于 2013-03-20T09:27:19.643 に答える