2015-07-11 55 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