0

I have an interface called Work

public class interface Work {
    boolean completeWork(Job j);
}

Then I have a Composite class

public class CompositeWork implements Work {
    private Set<Work> childWork = new HashSet<>();
    public boolean completeWork(Job j) {
        return childWork.stream().allMatch(w -> w.completeWork(j));
    }
    public void addWork(Work w) {
        childWork.add(w);
    }
}

I have a different Work types are the follwoing:

public class EasyWork implements Work {
    public boolean completeWork(Job j) {
        <do some work>
    }
} 

public class HardWork implements Work {
    private String id;
    public Hardwork(String id) {
        this.id = id;
    }
    public boolean completeWork(Job j) {
        <do some work>
    }
} 

Client populate CompositeWork something like this

public class Client {
    public static void main(String[] args) {
        CompositeWork workHolder = new CompositeWork();
        workHolder.add(new EasyWork());
        workHolder.add(new EasyWork());
        workHolder.add(new HardWork("1"));
        workHolder.add(new HardWork("2"));
    }
}

To enforce uniqueness of childWork in CompositeWork in HashSet<>() where do i implement hashcode() and equals()?

Does that occur in Work interface?
CompositeWork class?
or is it implemented inside EasyWork and HardWork?

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
ealeon
  • 12,074
  • 24
  • 92
  • 173

3 Answers3

1

Because you need to distinguish between EasyWork & HardWork, you need to implement those methods in those classes.

Here is a good article about this topic.

Gal Naor
  • 2,397
  • 14
  • 17
  • not only i want to distinguish bewteen EasyWork and HardWork, I may want to distinguish amongst themselves. from EasyWork(A) to EasyWork(B) – ealeon Apr 06 '19 at 20:30
1

We can't answer the question for you. It depends on how you want the classes to behave.

The default behavior for any class is that different instances will compare unequal to each other. If you are okay with all EasyWork objects being distinct and all HardWork objects being distinct, even when they contain the same data, then you don't need to do anything. The default methods may suffice.

Otherwise, you should examine each class on a case-by-case basis:

  • If you want HardWork objects to be equal if they have the same id, on the other hand, then you need to override equals() and hashCode() in HardWork. If not, don't bother.

  • Similarly, if EasyWork objects should be equal to each other then you'll need to override them there as well. If not, don't bother.

  • Furthermore, if you want CompositeWork objects to be equal to each other if they have the same Set of children then you should override them there, too. If not, don't bother.

John Kugelman
  • 349,597
  • 67
  • 533
  • 578
  • this may be an orthogonal question but is that mean equals uses hashcode to determine whether something is the same? then wouldnt just changing hashcode alone suffice? – ealeon Apr 06 '19 at 20:47
  • [If you override one, then you should override the other.](https://stackoverflow.com/questions/27581/what-issues-should-be-considered-when-overriding-equals-and-hashcode-in-java) – John Kugelman Apr 08 '19 at 01:38
1

I see the answer of John Kugelman and I almost agree. Almost - because there is one pretty important thing that is being often forgotten. If you are going to use EasyWork and HardWork objects in a hash-dependant collection like HashSet, besides overriding equals and hashcode you have to make your classes immutable. It means, that

  1. both of your classes have to be final
  2. fields, that are going to used by your equals and hashcode methods, have to be final.

Explanation

If the object is not immutable, then you can change some of its fields, then its hashCode will return a new result, and then you will be unable to access this object in collection due to a wrong location in hashtable.

Dzmitry Alifer
  • 409
  • 1
  • 6
  • 17