1

If I have a complex hierachy of inheritance and I want to do an equality check that depends on a specific equality is there a way to ensure I run using that equality check and not a version overridden by a child class that may behave different then I want?

To give an example lets say I have a foo with it's own equality class, and then I have something like boo with an equals class sort of like below sudocode (too lazy to right it out in full)

 class Foo {

   int id;
   int otherId;
   int count;

   public boolean equals(Object other){

     //check other instance of foo and re-cast

     return (id==other.id && otherId==other.otherId)
   }
}

class Bar extends Foo{

     private someObject uniqueValue;

     public boolean equals(Object other){

        //check other instance of foo and re-cast

        return super.equals(other) && other.getUniqueValue.equals(this.getUniqueValue);
   {
}

Then I have some method which takes too foo objects which reference the same foo and add up the counts for them

  public combineFoos(Foo foo1, Foo foo2){

      if(! foo1.equals(foo2))
          throw IllegalArgumentException("no match");

      Foo combinedFoo=new Foo(foo1.id, foo1.otherId, (foo1.count + foo2.count))

      return combinedFoo
   }
 }

In theory this all works, until the bar value comes in. Now if I call combineFoo and pass in a bar to foo1 it fails, because bars equal method checks foo2 is an instanceOf bar. I really don't care if foo2 is a bar, the information I need is available for any foo. For that matter if I pass in two unequal bars that both are equal as defined by foo's equality method (ie only the uniqueValue fields are different) I would want the combineFoo to still accept them as equal Foo's, even if not equal by Bar's definition.

The problem is that I want to do an equality check on exactly what a FOO considers as equal, but I don't know what bizarre inherited class I may actually receive. Is there a way to work around this, to basically say in my combineFoo to always use a FOOs definition of equals, even if it is overridden by a child class?

Related, would this be a far worse idea then I imagine it be even if doable, or is there some other way to handle something like the above example, short of effectively re-writing foo's equal method within the combineFoo?

dsollen
  • 6,046
  • 6
  • 43
  • 84
  • `Equals` is not `equals`. Use correct method. – MikeCAT Jun 07 '16 at 15:44
  • Your code has a lot of typos, it cannot compile as-is, making it hard to focus on the actual problem. – Tunaki Jun 07 '16 at 15:47
  • @tunaki As I said it is only sudocode, I left comments in for part of the logic. I was only trying to demonstrate conceptually the difference. I don't think running it is required to understand the concept is it? – dsollen Jun 07 '16 at 15:48
  • If the class `foo` has its own `equals` behavior and you're in control of calling it (rather than it's called by other code such as `Collection#contains`), then you might just add another method to `foo` that you declare `final` (hence it can't be overwritten in a subclass), e.g. `public final boolean fooEquals(foo other) { // custom foo equals logic }`. – forrert Jun 07 '16 at 15:52
  • IMHO your equals-method from Bar does not check for instance of foo2 but calls equals from foo, doesn't it? Anyway, you can get your behaviour by the idea of forret or just by defining the equals-method for foo and not for bar. If you have a bar calling equals, it should use the one of foo. – Supahupe Jun 07 '16 at 16:02

1 Answers1

0

Your equals methods fail the symmetry test, if a.equals(b) then b.equals(a). The obvious way to fix it would be to check the class like so:

   public boolean equals(Object other){
     if(other.getClass() != this.getClass()) return false;
     return (id==other.id && otherId==other.otherId)
   }

Having said that you may wish to allow some pairs of subclasses to be considered equal to each other - in which case I suggest you check out this question: Java - equals method in base class and in subclasses

Community
  • 1
  • 1
Matthew
  • 10,361
  • 5
  • 42
  • 54