Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is wrong with this design? Overriding or overloading of java.util.HashMap

This question was asked to me in MS interview. I wanna know the exact design issue in this piece of code. Code was already given, needed to find the design issue.

I have class MyHashMap which extends java HashMap class. In MyHashMap class I have to keep some information of employees. Key in this map will be firstName+lastName+Address .

public MyHashMap extends HashMap<Object, Object> {
  //some member variables 
  //
  public void put(String firstName, String lastName, String Address, Object obj) {
       String key =   firstName + lastName+ Address;
       put(key, obj);
  }

  public Object get(String firstName, String lastName, String Address) {
       String key =   firstName + lastName+ Address;
       return get(key);
  }

  public void remove(Strig key) {
        put(key, ""); 
  }

  //some more methods 
}

What is wrong with this design? Should I subclass HashMap or should I declare HashMap as member variable of this class? Or should I have implemented hashCode/equals methods?

like image 540
Ashish Avatar asked Feb 17 '10 10:02

Ashish


People also ask

What is overriding and overloading in Java?

Overriding occurs when the method signature is the same in the superclass and the child class. Overloading occurs when two or more methods in the same class have the same name but different parameters.

Why we use overloading and overriding in Java?

Method overloading is a compile-time polymorphism. Method overriding is a run-time polymorphism. It helps to increase the readability of the program. It is used to grant the specific implementation of the method which is already provided by its parent class or superclass.

Which of the following is true about overriding and overloading?

Overridden methods cannot be overloaded.

Can we override the overloaded method in Java?

So can you override an overloaded function? Yes, since the overloaded method is a completely different method in the eyes of the compiler.


3 Answers

There are quite a few problems, but the biggest problem I can see it that you're using a concatenated String as a key. The following two calls are different, but equivalent:

final MyHashMap map = new MyHashMap();

map.put("foo", "", "baz", new Object());
map.put("", "foo", "baz", new Object()); // Overwrites the previous call

There's also an issue that you're declaring that the key type as an Object, but always using String and are therefore not taking advantage of the type safety that comes with generics. For example, if you wanted to loop through the keySet of your Map, you'd have to cast each Set entry to a String, but you couldn't be sure that someone didn't abuse you Map by using an Integer key, for example.

Personally, I would favour composition over inheritance unless you have a good reason not to. In your case, MyHashMap is overloading the standard Map methods of put, get and remove, but not overriding any of them. You should inherit from a class in order to change its behaviour, but your implementation does not do this, so composition is a clear choice.

To act as an example, overloading rather than overriding means that if you make the following declaration:

Map<Object, Object> map = new MyHashMap();

none of your declared methods will be available. As recommended by some of the other answers, it would be far better to use an object composed of firstName, lastName and address to act as your map key, but you must remember to implement equals and hashCode, otherwise your values will not be retrievable from the HashMap.

like image 58
David Grant Avatar answered Sep 18 '22 23:09

David Grant


What's wrong with that design is primarily that is claims to be a HashMap<Oject, Object>, but isn't really. The overloaded methods "replace" the Map methods, but those are still accessible - now you're supposed to use the class in a way that is incompatible with the Map interface and ignore the (still technically possible) compatible way to use it.

The best way to do this would be to make an EmployeeData class with name and address fields and hashCode() and equals() methods based on those (or, better yet, a unique ID field). Then you don't need a non-standard Map subclass - you can simply use a HashMap<EmployeeData, Object>. Actually, the value type should be more specific than Object as well.

like image 42
Michael Borgwardt Avatar answered Sep 19 '22 23:09

Michael Borgwardt


I would go for declaring HashMap as member variable of your class.

I don't remember if a great explanation is given in Clean Code or Effective Java, but basically, it's simplier to do, requires less work if the API changes.

generally, extending such a class means you want to change its behavior.

like image 32
chburd Avatar answered Sep 19 '22 23:09

chburd