The instanceof operator

Figure 496. Defeating polymorphism Slide presentation
public static void main(String[] args) {
  final Shape[] shapes = {
    new Circle(1, 1, 2.),
    new Rectangle(1, -1, 2., 3.)};
  print(shapes);
}
static void print(final Shape[] shapes) {
  for (final Shape s : shapes) {
    if (s instanceof Rectangle) {
      System.out.println("Type Rectangle");
    } else if (s instanceof Circle) {
      System.out.println("Type Circle");
    }
  }
}
Type Circle
Type Rectangle

Figure 497. Defining equals(...): Expectations Slide presentation
Rectangle r1 = new Rectangle(1, 2, 5, 4),
          r2 = new Rectangle(1, 2, 1, 7),
          r3 = new Rectangle(1, 2, 5, 4);

Circle c = new Circle(-2, 3, 5);

System.out.print(r1.equals("Hi"));//false: Differing classes Rectangle and String.
System.out.print(r1.equals(r2));  //false: Differing width and height.
System.out.print(r3.equals(r1));  //true:  Two rectangles having identical
                                  //       (x|y), width and height.
System.out.print(r1.equals(c));   //false: Differing classes Rectangle and Circle.
System.out.print(c.equals(c));    //true: Object equal to itself.

Figure 498. Defining equals(...) of Shape instances Slide presentation

Two Shape instances shall be considered equal if:

  • Both instances are of common type i.e. either Rectangle or Circle.

  • Their center coordinates match within a threshold of 10 - 15 .

  • width and height or radius match within a threshold of 10 - 15 .


Figure 499. Comparing center coordinates Slide presentation
public abstract class Shape {
  private double x, y;

  protected boolean equalCenter(final Shape o) {
      return Math.abs(o.x - x) + Math.abs(o.y - y) < 1.E-15;
  }
...

Figure 500. Implementing Rectangle.equals() Slide presentation
public class Rectangle extends Shape {
    @Override public boolean equals(Object o) {
    if (o instanceof Rectangle r) {

      final Rectangle oRectangle = (Rectangle) o; // Cast is «legal»
      return super.equalCenter(r) &&
             Math.abs(r.width- width) +
                 Math.abs(r.height- height) < 1.E-15;
    }
    return false;
  }
 ...

For o == null the expression o instanceof Rectangle evaluates to false.


Figure 501. Implementing Circle.equals() Slide presentation
public class Circle extends Shape {
  @Override public boolean equals(final Object o) {
    if (o instanceof Circle c){
      return super.equalCenter(c) &&
        Math.abs(c.radius - radius) < 1.E-15;
    }
    return false;
  } ...

Figure 502. Testing equality of Shape objects Slide presentation
final Rectangle
    r1 = new Rectangle(2, 3, 1,4),
    r2 = new Rectangle(2, 3, 2,8),
    r3 = new Rectangle(2, 3, 1,4);

final Circle c = new Circle(2,3, 7);

System.out.println("r1.equals(r2): " + r1.equals(r2));
System.out.println("r1.equals(r3): " + r1.equals(r3));
System.out.println("c.equals(r1): " + c.equals(r1));
r1.equals(r2): false
r1.equals(r3): true
c.equals(r1): false