2012-04-10 58 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);