2

I have an abstract Java class that has a hashcode field that should be initialized by the concrete subclasses. I was thinking of making the initialization method abstract, i.e.,

abstract class A {
  protected int hashcode;
  // hashcode should be initialized in constructor
  protected A () { hashcode = setHashcode(); }
  abstract int setHashcode() {} // implemented by subclasses
}

But unfortunately different subclasses need to take in different number of arguments for setHashcode, e.g., class B might compute hashcode using two of its fields and class C might need three, but since the call to super has to be the first line in B's constructor this scheme won't work. So I am wondering if there is a different way / design pattern to solve this problem?

JRR
  • 6,014
  • 6
  • 39
  • 59
  • As a note on style: it is awkward to have a method named `setSomething()` which does not set any value but instead returns the calculated value. `calculateHashcode` or `determineHashcode` might do better job expressing the intent of the method. – Jake Greene Apr 10 '12 at 03:35
  • You might find the information in [this question](http://stackoverflow.com/questions/7223435/java-call-base-method-from-base-constructor), and [this question](http://stackoverflow.com/questions/7477553/in-java-is-there-a-legitimate-reason-to-call-a-non-final-method-from-a-class-co) useful. – Kevin K Apr 10 '12 at 03:37

4 Answers4

2

but since the call to super has to be the first line in B's constructor this scheme won't work

Why wouldn't it work? If you put calculations of the hash code in a static function of a subclass, you would be able to pass pre-made hash code to the constructor of your superclass.

class BaseClass {
    private int hashCode;
    protected BaseClass(int hashCode) {this.hashCode = hashCode;}
}
class DerivedClass : BaseClass {
    private static int calcHash(String str) {
        return str.hashCode();
    }
    public DerivedClass(String s) {
        super(calcHash(str));
    }
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
2

You don't really need to store the value in the superclass, just declare an abstract getHashCode that subclasses will override.

public abstract class Base {
  protected abstract int getHashCode();
}

This is better because the "intent" of the method is preserved, regardless of its storage requirements.

Incidentally, hashCode is already defined in Object, and can be overridden by subclasses. If your concept of hash code is different than what Object provides, maybe you should rename it.

Jordão
  • 55,340
  • 13
  • 112
  • 144
1

It sounds like an interface might be appropriate for the initialization so any subclasses you create can just overload the interface implementation.

DJ Chateau
  • 148
  • 1
  • 11
0

Change:

abstract int setHashcode(); 

To:

abstract int getHashcode(Object...objects); 

And the subclass needs to inspect the count and type of objects passed.

Then you make calls like:

  hashcode = getHashcode(); 
  hashcode = getHashcode(o1); 
  hashcode = getHashcode(o1,o2); 
Java42
  • 7,628
  • 1
  • 32
  • 50