2012-04-10 57 views
2

我有一个抽象的Java类,它有一个应由具体子类初始化的散列码字段。我想使初始化方法抽象的,即,在子类中设置超类字段

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

但不幸的是不同的子类需要采取不同数量的参数为setHashcode,例如,B类可能会使用它的两个字段和C类强权计算哈希码需要三个,但由于超级的调用必须是B的构造函数中的第一行,所以此方案不起作用。所以我想知道是否有不同的方式/设计模式来解决这个问题?

+0

作为风格注:这是尴尬的有一个名为'setSomething()'方法不设置任何值,而是返回计算值。 'calculateHashcode'或'determineHashcode'可能会更好地表达方法的意图。 – 2012-04-10 03:35:35

+0

您可能会在[此问题]中找到相关信息(http://stackoverflow.com/questions/7223435/java-call-base-method-from-base-constructor),以及[this question](http:// stackoverflow .com/questions/7477553/in-java-is-there-a-legal-reason-to-call-a-non-final-method-from-a-class-co)有用。 – 2012-04-10 03:37:48

回答

2

但由于调用超级必须是在B的构造函数中的第一行

为什么不是工作,该方案将无法正常工作?如果你把散列码的计算放在一个子类的静态函数中,你可以将预先制作的散列码传递给你的超类的构造函数。

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)); 
    } 
} 
2

你并不真正需要的值存储在超类,只是声明一个抽象getHashCode子类会覆盖。

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

这样更好,因为无论存储需求如何,该方法的“意图”都会被保留。

顺便提一下,hashCode已经在Object中定义了,可以被子类覆盖。如果你的散列码的概念与Object提供的不同,也许你应该重命名它。

1

听起来像一个接口可能适合于初始化,所以你创建的任何子类都可能会超载接口实现。

0

变化:

abstract int setHashcode(); 

要:

abstract int getHashcode(Object...objects); 

类和子类需要检查传递的对象的数量和类型。

然后做个像电话:

hashcode = getHashcode(); 
    hashcode = getHashcode(o1); 
    hashcode = getHashcode(o1,o2);