2015-12-21 32 views
0

我有一个带有静态变量的基类。我想创建派生子类,它将自动拥有自己的未共享静态变量。理想情况下,应该是这样的:自动为每个派生类创建一个静态变量的副本

class Parent 
{ 
    Texture2D picture; 
    static Texture2D pictureOrigin; 

    Parent() 
    { 
     picture = pictureOrigin; 
     /*Loading the static origin to an instance variable 
     because I might want to have more pictureOrigins 
     and alternate them or perhaps change the picture 
     of the instance based on a certain event, etc.*/    
    } 
} 

class Subclass1 : Parent //Edit: forgot to write the inheritance in this example 
{ 
    Subclass1() : base() 
    { } 
} 

class Subclass2 : Parent 
{ 
    Subclass2() : base() 
    { } 
} 

void main() 
{ 
    Parent.pictureOrigin = Load("pictureForParent"); 
    Subclass1.pictureOrigin = Load("pictureForSubclass1"); 
    Subclass2.pictureOrigin = Load("pictureForSubclass2"); 
    //Then creating instances of the classes and drawing them, etc. 
} 

但发生的事情是,他们都获得了最后的加载图像(pictureForSubclass2),因为静态变量pictureOrigin在它们之间共享。

最快锁定被手动添加新的静态变量pictureOrigin到每个子类和隐藏的基类的pictureOrigin变量:

class Subclass1 : Parent 
{ 
    new static Texture2D pictureOrigin; 

    Subclass1() : base() 
    { 
     picture = pictureOrigin; 
    } 
} 

此外,在创建抽象方法或类似,以确保新的静态变量的创建在子类中。但它似乎太麻烦,不太优雅。有没有更好的方法来做到这一点?

+0

静态看起来像一个坏主意,它为什么必须是静态的任何理由?您可以将图像资源加载到某个图像存储区,然后将所需图像提供给每个实例? –

+0

在您的代码中,Subclass1和Subclass2不是从Parent继承的。 –

+0

您可以使'Parent'通用,就像'父Parent 其中T:Parent ',然后继承指定子类的类型:'class Subclass1:Parent '。然后你会利用这样一个事实,即每个“”类型的独特组合将获得他们自己的所有静态字段的副本。话虽如此,我会尽量摆脱'static'关键字,并找到一种不同的方式来做到这一点。 –

回答

1

你的问题闻起来像一个糟糕的设计。在我看来,静态变量通常是不好的实践,适当的面向对象设计可以消除永远使用静态成员的需要。

尝试重构像这样:

public class Parent 
{ 
    private Texture2D texture; 

    public Parent(Texture2D texture) { 
     this.texture = texture; 
    } 

    public Texture2D Picture { get { 
      return texture; 
     } 
    } 
} 

public class SubClass1 : Parent 
{ 
    public SubClass1(Texture2D texture) : base(texture) { 

    } 
} 

让我解释为什么静态是一个糟糕的选择:

  1. 你的类现在只为一个位图不错。消除了重用类的几个位图的可能性(这是你正在对抗的限制)
  2. 直到调用静态setter后,你的类才会处于有效状态。一般而言,构建的对象应该处于有效状态。如果他们使用你的对象,他们必须静态设置类的位图,这对别人来说并不明显。
  3. 打破自然垃圾收集。例如,如果您希望在收集SubClass的所有实例时对Texture2D对象进行垃圾收集,则它不适用于您的静态设计。或者,如果您使用oop设计(如建议),您可以灵活地进行垃圾收集,而不取决于您的使用情况。
  4. 使线程更复杂。静态属性是全局的,所以您需要全局互斥来保证线程安全。
  5. 使测试更加困难。如果你想单元测试这个类,你必须确保在每次测试之后静态被清除,并且你不能同时对这个类运行两个单元测试。
  6. 使内存管理不灵活。如果您使用面向对象的设计,则可以选择在所有实例之间共享位图,或为每个实例分配一个新的位图。
+0

我有一个游戏。父母定义了游戏的一些一般对象(如坐标,移动方法等)。子类是具有已定义属性的实际对象,但它们的图片必须从Game类加载。我曾经给他们提供了构建'someObject(int x,int y,Texture2D pic)'的图片,但将图片保存到类中似乎更好,所以我不必每次将它发送给构造函数类的实例。 – pavelkomin

+0

构造函数听起来像是一个更好的方法来实际执行它。不要担心传递引用,因为它只是一个引用。每次将它传递给构造函数时,它都不会复制图像,所以如果使用构造函数构造它们,您将获得在所有实例之间共享内存的好处对同一个Texture2D的引用。 – Samuel

0

听起来像virtual关键字的工作。

virtual关键字用于修改方法,属性,索引器或事件声明,并允许在派生类中重写它。

https://msdn.microsoft.com/en-us/library/9fkccyh4.aspx

+2

“你不能在静态,抽象,私有或覆盖修饰符中使用虚拟修饰符” – Samuel

+0

正确...它必须重新设计......但我只是说...这就是继承的目的和虚拟关键字。 – kevindeleon

1

你可以用静态Dictionary<Type,Texture2D>来做到这一点。

public class Parent 
{ 
    // Keep a table of types and default values 
    protected static Dictionary<Type, Texture2D> pictureOrigin; 

    static Parent() 
    { 
     // static ctor. initialize table 
     pictureOrigin=new Dictionary<Type, Texture2D>(); 
    } 

    internal static void SetDefaultPicture<T>(Texture2D picture) 
    { 
     // Set default based on type T 
     Type type=typeof(T); 
     pictureOrigin[type]=picture; 
    } 

    public Parent() 
    { 
     // Assign default based on this type 
     Picture=pictureOrigin[this.GetType()]; 
    } 
    public Texture2D Picture { get; set; } 
} 

public class SubClass1 : Parent 
{ 
} 
public class SubClass2 : Parent 
{ 
} 

用作

static void Main(string[] args) 
    { 
     Texture2D picture0 = Load("pictureForParent"); 
     Texture2D picture1=Load("pictureFroSubClass1"); 
     Texture2D picture2=Load("pictureFroSubClass2"); 

     Parent.SetDefaultPicture<Parent>(picture0); 
     Parent.SetDefaultPicture<SubClass1>(picture1); 
     Parent.SetDefaultPicture<SubClass2>(picture2);    
    } 

下面是一个例子的调试。它显示SubClass1自动初始化为pictureForSubClass1

res

相关问题