2014-01-11 85 views
0

我有幾個類都繼承相同的基類,需要有一個靜態屬性在啓動時在函數中初始化。我這樣實現它:受保護的靜態成員的繼承類

public abstract class Base { 
    protected static Model model; 
} 

public class Inherited extends Base { 
    static { 
     model = initializationFunction(); 
    } 
} 
public class OtherInherited extends Base { 
    static { 
     model = otherInitializationFunction(); 
    } 
} 
// Example of use 
Base[] inheriteds = new Base[] { new Inherited(), new OtherInherited() }; 
for (int i = 0; i < inheriteds.length; i++) { 
    doStuff(inheriteds[i]).model; // This will always use the same model (last defined) 
} 

所以類在開始時初始化靜態成員。但它似乎爲整個基類設定了模型的價值,所以所有的類實際上都有相同的模型。

我需要model是靜態的,因爲它需要每個子類只存在一次。我的問題是如何爲每個子類創建一個靜態模型,同時仍然確保它在父類中定義(所以如果一個類沒有定義它,它在父類中定義)。

受保護靜態成員在繼承類中的預期行爲是什麼?我應該如何去讓每個類的這個成員的版本仍然是靜態的(我不希望它爲每個實例重複)?

+2

的靜電場屬於基地,無論你來自哪裏,訪問它。 –

+2

這很簡單 - 靜態對象引用只存在一次。你爲什麼把它變成靜態的? – home

+0

如果模型綁定到子類,那麼它應該在子類中聲明,而不是在基類中聲明。 –

回答

2

我的問題是如何讓每個子類一個靜態模型,同時還 確保它在父類中的定義(因此,如果一個類沒有 定義它,它是在父類中定義)。

沒辦法,因爲,靜態成員和多態性,繼承不要一起去

+0

這是否意味着我不應該在繼承類上使用靜態字段?如果我在子類中定義我的成員,那麼迭代Base數組的模型可能是一個問題(如果其中一個子類沒有模型定義) – Malharhak

+0

@Malharhak:你不能指望靜態多態行爲fileds/mathods in Java –

1

繼承不適用於靜態字段(即類字段)工作。所以只有一個字段Base.modelInherited.model指的是相同的字段。

1

如果您確實需要模型的解決方案是自動的,而不是讓devoloper確保一致性,那麼您需要自己實現整個機制,因爲Java的語言功能將不會直接處理該問題。

其中一個選項是沿着Singleton路線行進,其中單身人士將是Model工廠。不要直接訪問靜態字段來獲取模型,而是要求各個類的工廠單例獲取它。工廠本身將繼承基本工廠,因此您可以通過多態性獲得「自動默認」行爲。

1

正如其他答案所建議的,靜態成員的範圍是在類級別而不是在對象級別,簡言之,不是繼承層次結構的任何部分。靜態成員的類名稱只是一個額外的名稱空間限定符。這裏是關於靜態關鍵字的一個很好的簡介:http://mindprod.com/jgloss/static.html

至於解決你的問題,我在此仍然使用靜態成員的裂縫。如果你真的必須有一個子類的每個實例共享相同的模型實例,同時保持某種接口的兼容性與基類再考慮做類似如下:

public abstract class Base { 
    public abstract Model getModel(); 
} 

public class Inherited extends Base { 
    static private Model model = initializationFunction(); 

    public Model getModel() { 
     return model; 
    } 
} 

public class OtherInherited extends Base { 
    static private Model model = otherInitializationFunction(); 

    public Model getModel() { 
     return model; 
    } 
} 

事實上這裏涉及到靜態成員被從界面中隱藏起來,這是一個很大的勝利。如果您在不使用靜態成員的情況下達到可以解決此問題的程度,那麼您的類層次結構的客戶端將不會受到影響,因爲訪問模型根本不公開使用靜態成員的實現細節。

0

也許管理模型對象以某種方式:

public abstract class TestBase { 

    private static Map<Class, Object> modelObjects = new HashMap<>(); 

    public static void setModel(Class _class, Object model) { 
     modelObjects.put(_class, model); 
    } 

    public static Object getModel(Class _class) { 
     return modelObjects.get(_class); 
    } 

    public static class Inherited extends TestBase { 

     static { 
      setModel(Inherited.class, new Object()); 
     } 
    } 

    public static class OtherInherited extends TestBase { 

     static { 
      setModel(OtherInherited.class, new Object()); 
     } 
    } 
}