-1

So this is the part of the Unit test:

public class LocationTester {

private Floor seventhFloor;
private int size = 10;

@Before
public void setup() {
    size = 10;
    seventhFloor = new Floor(7, size);
}

@Test
public void testLocationEquality() {
    Location l1 = new Location(seventhFloor, 3, 3);
    Location l2 = new Location(new Floor(7, size), 3, 3);
    assertTrue(l1.equals(l2));
}}

Here's the part of Location class with method equals:

class Location {

private Floor floor;
private int size, position;

    @Override
public boolean equals(Object obj) {
    if (obj == null) {
        return false;
    }
    if (obj == this) {
        return true;
    }
    if (obj instanceof Location) {
        return false;
    }
    return equals((Location) obj);
}

public boolean equals(Location loc) {
    return floor.equals(loc.floor) && position == loc.position && size == loc.size;
}

And here's the part of Floor class:

class Floor {

private int number;

    public boolean equals(Floor floor) {
    return number == floor.number;
}

I don't know why equals method with parameter (Object obj) and typecasting is put when "new Location" at " Location l2 = new Location(new Floor(7, size), 3, 3);" is actually the object of Location itself. Why is it needed to put the equals(Object obj).

The test runs fine without the method equals(Object obj).

Not to mention, there is no subclass of Location in this project. So why put typecasting at "return equals((Location) obj);" anyway?

Bob
  • 3
  • 3
  • 3
    Why *what* returns true? `equals(Object)`, `equals(Location)` or `equals(Floor)`? Please clarify, ideally reducing this to a [mcve] to provide even less scope for lack of clarity. – Jon Skeet Aug 27 '17 at 11:23
  • Note that there should be a compile error in this example - Location's `equals(Location loc)` is accessing objects private fields. – Janez Kuhar Aug 27 '17 at 11:26
  • 3
    @JanezKuhar A method inside `Location` is permitted to access `Location`'s private field. – khelwood Aug 27 '17 at 11:29
  • @JonSkeet I updated my question. I'm sorry for the confusion – Bob Aug 27 '17 at 11:34
  • @khelwood I can't believe this - I've just tested it and seen it with my own eyes. What a violation of encapsulation! `this` can reference `loc`'s private fields! How is this even possible?:( – Janez Kuhar Aug 27 '17 at 12:00
  • @JanezKuhar: there's no violation of encapsulation or private modifiers, since this is all occurring within the Location class code. Within the class private fields are accessible even for non-this objects. Edit, as khelwood already tells you. You may wish to study on this subject a bit more. – Hovercraft Full Of Eels Aug 27 '17 at 12:02
  • @HovercraftFullOfEels But the whole point of encapsulation is that no 2 objects can have direct access to each others private fields - even those of the same type. That's what's puzzling to me. – Janez Kuhar Aug 27 '17 at 12:03
  • 2
    @JanezKuhar: the principle behind encapsulation is to prevent *unauthorized* objects access to certain data, the key word here being ***unauthorized***, one which you and Java appear to define differently. – Hovercraft Full Of Eels Aug 27 '17 at 12:06
  • 2
    @JanezKuhar not two *objects*, two *classes*. A class should not see another class's private members. But encapsulation says nothing about two instances *of the same class*. – RealSkeptic Aug 27 '17 at 12:08
  • @RealSkeptic, Hovercraft Full Of Eels From Wikipedia on Encapsulation: *A language mechanism for restricting direct access to some of the **object**'s components.* – Janez Kuhar Aug 27 '17 at 12:10
  • @JanezKuhar: from the same article: *"preventing unauthorized parties' direct access to them."* Again the definition of unauthorized is key. – Hovercraft Full Of Eels Aug 27 '17 at 12:17
  • 1
    @JanezKuhar: please see [this related question](https://stackoverflow.com/questions/17027139/access-private-field-of-another-object-in-same-class) on why Java uses class-level access modifiers rather than object-level modifiers. – Hovercraft Full Of Eels Aug 27 '17 at 12:22
  • @JanezKuhar that Wikipedia article is sloppy, as it uses "object" and "class" interchangeably. The examples are also questionable. The fact is that whoever writes the code of the class is already able to see all those fields, so it's perfectly OK to access them. Encapsulation is not a security measure, it's a technique for clean programming. – RealSkeptic Aug 27 '17 at 12:23

1 Answers1

1

Your test actually tests only the equals(Location) method. It doesn't test the equals(Object) method.

However, the equals(Object) exists in the class in order to override the one from Object.equals(Object), which requires that the parameter is any Object.

If, in some program, you assign a Location object to an Object variable:

Object a = new Location(...);
Object b = new Location(...);

And you then use a.equals(b), it won't use the location's equality test, and will always return false, even if the two instances designate the same location - unless you have a proper equals(Object) method - which is what you have here.

And in that equals(Object) method, because its parameter is of type Object, if you do not cast it to Location, it will call itself recursively forever. You have to cast it in order for it to ultimately call the equals(Location) method which contains the actual equality test.

In fact you could do without equals(Location) and just write the test in the equals(Object), but I suppose the author wanted to save the three test steps in cases where it is known at compile time that the tested object is a Location.

RealSkeptic
  • 33,993
  • 7
  • 53
  • 79
  • So if I had "Object o1 = new Location(seventhFloor, 3, 3);" inside the unit test, the "return equals((Location) obj);" inside the equals(Object obj) will come to purpose? Because the object o1 will be downcasted to the type Location am I right? – Bob Aug 27 '17 at 12:30
  • @Bob If either `l1` or `l2` was an `Object` instead of `Location`, then yes, the `equals(Object)` method would be called. You can add a print to that method and see for yourself. – RealSkeptic Aug 27 '17 at 12:33
  • Thank you kindly. now I understand and the purpose of the equals(Object obj) and its casting sentence. Even though it's not needed in my case, it's still a good practice. – Bob Aug 27 '17 at 12:49
  • Thank you, I did. – Bob Aug 27 '17 at 13:46