我可以为每种不同类型的继承类拥有不同的静态变量副本吗

Posted

技术标签:

【中文标题】我可以为每种不同类型的继承类拥有不同的静态变量副本吗【英文标题】:Can I have different copies of a static variable for each different type of inheriting class 【发布时间】:2010-11-29 16:54:37 【问题描述】:

我希望根据类的类型拥有具有不同值的相同静态变量。

所以我会的

public class Entity

     public static Bitmap sprite;

     public void draw(Canvas canvas, int x, int y)
     
          canvas.drawBitmap(sprite, x, y, null);
     


public class Marine extends Entity




public class Genestealer extends Entity



然后在我的主程序中运行:

Marine.sprite = // Load sprite for all instances of Marine
Genestealer.sprite = // Load sprite for all instances of Genestealer

我不想在类的每个实例中存储相同的精灵。我想要一个用于每种类型的课程。我想继承静态精灵变量和绘制精灵的绘制函数。但我不希望 Genstealer 精灵覆盖 Marine 精灵。

这可能吗?

我该怎么做?

【问题讨论】:

甚至你的 gravatar 也是穿着太空海洋盔甲的燕尾服企鹅 - 太棒了:) 我想你也可以在父类中用“抛出新的 UnsupportedOperationException”来定义它,如果你有某些子类从没想过会有精灵(尽管这也意味着你会失去编译时间检查) . 【参考方案1】:

使用抽象方法:

public class Entity

     public abstract Bitmap getSprite();

     public void draw(Canvas canvas, int x, int y)
     
          canvas.drawBitmap(getSprite(), x, y, null);
     


public class Marine extends Entity

    public Bitmap getSprite() 
        return /*the sprite*/;
    

getSprite 返回的精灵可以是静态的,如果你喜欢的话。这种方法的优点:

您不能(轻易)忘记在子类中包含精灵,因为如果您不实现抽象方法,编译器会报错。

它很灵活。假设一名海军陆战队员“升级”后看起来应该有所不同。只需更改 Marine 的 getSprite 方法以考虑关卡。

这是此类事情的标准 OO 习惯用法,因此查看其代码的人不会摸不着头脑。

【讨论】:

【参考方案2】:

我有同样的问题,并找到了使用静态映射的解决方案

类 --> 对象。

以下代码示例使用 Integer 作为所需“类静态”变量的类型。

import java.util.Map;
import java.util.HashMap;

class C

    static Map<Class<?>,  Integer> class2IntegerMap = new HashMap<Class<?>, Integer>();


    public void setClassSpecificInteger(Integer _i)
    
        class2IntegerMap.put(this.getClass(), _i);
    

    public Integer getClassSpecificInteger()
    
        return class2IntegerMap.get(this.getClass());    
               


class CA extends C



class CB extends C



class CAA extends CA



public class MainClass

    public static void main(String []args)
    
        CA a1 = new CA();
        CA a2 = new CA();
        CB b1 = new CB();
        CB b2 = new CB();
        CAA aa1 = new CAA();

        a1.setClassSpecificInteger(Integer.valueOf(-1));
        b1.setClassSpecificInteger(Integer.valueOf(+33));

        System.out.println("The int-value for a1 is: "+a1.getClassSpecificInteger());
        System.out.println("The int-value for b1 is: "+b1.getClassSpecificInteger());

        System.out.println("The int-value for aa1 is: "+aa1.getClassSpecificInteger());

        System.out.println("The int-value for a2 is: "+a2.getClassSpecificInteger());
        System.out.println("The int-value for b2 is: "+b2.getClassSpecificInteger());

        CA a3 = new CA();
        CB b3 = new CB();

        System.out.println("The int-value for a3 is: "+a3.getClassSpecificInteger());
        System.out.println("The int-value for b3 is: "+b3.getClassSpecificInteger());

        CAA aa2 = new CAA();

        aa2.setClassSpecificInteger(Integer.valueOf(8));

        System.out.println("The int-value for aa1 now is: "+aa1.getClassSpecificInteger());
     
 

输出是:

The int-value for a1 is: -1
The int-value for b1 is: 33
The int-value for aa1 is: null
The int-value for a2 is: -1
The int-value for b2 is: 33
The int-value for a3 is: -1
The int-value for b3 is: 33
The int-value for aa1 now is: 8

我希望这对某人有所帮助。请善待。

【讨论】:

【参考方案3】:

在超类中不可能是静态的。超类中的静态变量由所有子类共享(实际上是单例)。任何时候您更改它(例如,通过实例化子类),该更改都会反映在所有其他子类实例中。

相反,在子类中将 sprite 设为静态,然后使用 Laurence 描述的方法结构。

【讨论】:

这是原始问题的答案,其他答案必须得到相同的行为。但答案是否定的,C# 没有针对父类中定义的每个子类的静态变量的 anycon 构造。【参考方案4】:

所以制作一个 Sprite 并给每个人实例变量。它们只是参考;只不过是指针而已。

【讨论】:

【参考方案5】:

一个快速测试将告诉您,是的,您可以覆盖子类中的静态变量。

我已经整理了一个简单的继承结构来测试它。 StaticTest 是 StaticTestSub 的上级。它们都声明了具有不同访问权限的静态整数 TEST1TEST2TEST3。为了简化示例,我省略了private 版本。

public class StaticTest 
    public static int TEST1 = 1;
    protected static int TEST2 = 1;
    static int TEST3 = 1;

    public static void main(String[] args) 
            System.out.println("StaticTest.TEST1: " + StaticTest.TEST1);
            System.out.println("StaticTest.TEST2: " + StaticTest.TEST2);
            System.out.println("StaticTest.TEST3: " + StaticTest.TEST3);
            System.out.println("StaticTestSub.TEST1: " + StaticTestSub.TEST1);
            System.out.println("StaticTestSub.TEST2: " + StaticTestSub.TEST2);
            System.out.println("StaticTestSub.TEST3: " + StaticTestSub.TEST3);
    



public class StaticTestSub extends StaticTest 
    public static int TEST1 = 2;
    protected static int TEST2 = 2;
    static int TEST3 = 2;

你可以在家里试试这个。输出是:

StaticTest.TEST1: 1 静态测试.TEST2:1 静态测试.TEST3:1 StaticTestSub.TEST1: 2 StaticTestSub.TEST2: 2 静态测试子.TEST3:2

但是,对于您的特定需求,我推荐 Laurence Gonsalves 采用的方法

【讨论】:

以上是关于我可以为每种不同类型的继承类拥有不同的静态变量副本吗的主要内容,如果未能解决你的问题,请参考以下文章

继承抽象static

Java多态之动态绑定

static关键字

iOS swift中值类型与引用类型的不同

如何使用模板专门化常量

C存储类链接和内存管理——存储类