2015-07-11 106 views
2

我要創建的數據結構來捕獲以下思路:正在用靜態塊錯誤操作覆蓋靜態字段?

在一場比​​賽中,我希望有一個通用的Skill類,像捕捉技能ID的一般信息,降溫時間,法力消耗等

然後我想要具備定義實際交互和行爲的特定技能。所以這些都會從基類Skill延伸。

最後,每個球員都會有這些特殊技能的情況下,這樣我就可以檢查每個玩家的技能狀態,玩家是否用它最近,等

所以,我有一個抽象超Skill定義一些靜態變量,所有技能都有共同之處,然後對於每個延伸Skill的個人技能,我都使用靜態塊來重新分配靜態變量。所以我有以下模式:

class A { 
    static int x = 0; 
} 

class B extends A { 
    static { 
     x = 1; 
    } 
} 

... 

// in a method 
A b = new B(); 
System.out.println(b.x); 

上面的打印1,這正是我想要的行爲。我唯一的問題是系統抱怨我以非靜態方式訪問靜態變量。但是我當然不能以這種方式訪問​​它,因爲我只想把技能看作Skill而不知道它是哪個子類。所以我不得不在每次做這個時都壓制這個警告,這讓我想到這裏是否有更好的/更漂亮的設計模式。

我曾經想過問題非靜態使得變量,而是因爲他們要跨越特定技能的所有實例是靜態的,我覺得這應該是一個靜態變量...

+0

如果每個技能的子類都有自己的x的值,那麼你應該有一個每個子類中的靜態'x'字段。原樣,加載類B將A.x設置爲1.使x變量最終確定。如果你想以多態的方式訪問一個變量值,那麼你應該在每個類中都有一個非靜態的'getX()'方法。它是否總是返回相同的常量值是一個實現細節。 –

+0

問題是......你不改變特定技能的所有實例,而是改變所有技能的所有實例,因爲你改變了類'A'中的屬性(我認爲它是你的'AbstractSkill'類)。因此對於所有擴展了'A'的類,'x'是'1'。我傾向於使用接口來提供技能,定義所需的方法並隱藏實現細節。你可以有一些'public int getX()'而不關心實現。 – Turing85

+1

這只是一個完整的擱置,但我會完全分開這兩件事:我有一個'SkillInfo'類/枚舉,其中包含有關技能的所有通用信息(名稱,描述,先決條件等) ,技能不會延伸,每個人都有一個實例。你可以創建獨立的類來實現技能行爲,每種技能一個。 – biziclop

回答

2

你通常應該避免使用這種全球狀態。如果你確實知道該字段x將在之間共享所有實例全部基類的子類型,那麼放置這樣的字段的正確位置可能是基類以外的其他地方。它可能在一些其他配置對象中。

但即使使用您當前的配置,它也沒什麼意義,因爲修改靜態變量的任何子類都將使變量對所有類都可見。如果子類Bx更改爲1,則子類C將其更改爲2,新值也將顯示爲B

我認爲你在問題中描述的方式,每個子類都應該有自己獨立的靜態字段。而在抽象基類,你可以以訪問每個字段定義一個方法由每個子類實現:

abstract class A { 

    public abstract int getX(); 
} 

class B extends A { 
    public static int x = 1; 

    public int getX() { 
     return x; 
    } 
} 

class C extends A { 
    public static int x = 2; 

    public int getX() { 
     return x; 
    } 
} 
+0

嗯,看來我應該對它進行更廣泛的測試。但是,你將如何建模?我認爲我的問題是我想要聲明一個我認爲應該是靜態的抽象方法/字段,因爲在子類中,值在所有實例中都是不變的。 –

+0

抽象字段沒有這種東西,抽象方法不能是靜態的。我認爲你在問題中描述的方式,每個子類都應該有自己獨立的靜態字段。 – manouti

+0

但這樣我就失去了抽象。例如,我不能遍歷一個'Skill'列表,我知道它們每個都有一個名爲'foo'的靜態變量,而不知道每個實例的子類。我也不想用反射。 –

1

前面已經指出的一些答案和意見,你的做法是行不通的路你想要的是因爲每個靜態塊都會更改所有延伸爲A的類的靜態變量。

使用的界面和實例方法代替:

public interface A { 
    int getX(); 
} 

-

public class B implements A { 

    private static final int X = 1; 

    @Override 
    public int getX() { 
     return X; 
    } 
} 

-

A myInstance = new B(); 
System.out.println(myInstance.getX()); // prints "1" 
+0

但是,由於B的所有實例的值都是不變的,所以我覺得將它作爲A知道的靜態方法會更加優雅......我猜這在Java中真的不被支持...... –

+0

只有B的所有實例都是X的一個靜態實例。但正如您猜對的那樣,無法使用A中定義的靜態字段或方法來執行所需操作。 – hzpz