为每个派生自动创建静态变量的副本 class
Automatically create a copy of a static variable for each derived class
我有一个带有静态变量的基 class。我想创建派生的 subclasses,它会自动拥有自己的非共享静态变量。理想情况下它看起来像这样:
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
{
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
到每个子 class 并隐藏基础 class:
的 pictureOrigin
变量
class Subclass1 : Parent
{
new static Texture2D pictureOrigin;
Subclass1() : base()
{
picture = pictureOrigin;
}
}
或者,创建抽象方法或类似方法以确保在子classes 中创建新的静态变量。但这似乎太麻烦而且不太优雅。有更好的方法吗?
你的问题设计得很糟糕。在我看来,静态变量通常是不好的做法,适当的面向对象设计可以消除使用静态成员的需要。
像这样尝试重构:
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) {
}
}
让我详细说明为什么静态是一个糟糕的选择:
- 您的 class 现在仅适用于单个位图。消除了为多个位图重用 class 的可能性(这是您要反对的限制)
- 在调用静态 setter 之前,您的 class 未处于有效状态。通常,对象一旦构造,就应该处于有效状态。如果其他人正在使用您的对象,他们必须在 class.
上静态设置位图,这对其他人来说并不明显
- 破坏自然垃圾收集。例如,如果您希望在收集 SubClass 的所有实例时对 Texture2D 对象进行垃圾收集,那么它不适用于您的静态设计。或者,如果您使用 oop 设计(如建议的那样),您可以根据您的用例灵活地进行垃圾收集或不进行垃圾收集。
- 使线程更复杂。静态是全局的,所以你需要全局互斥锁来保证线程安全。
- 使测试更加困难。如果你想对 class 进行单元测试,你必须确保每次测试后静态都被清除,并且你不能 运行 针对这个 class 并行进行两个单元测试.
- 使内存管理不灵活。如果您使用面向对象的设计,您可以选择在所有实例之间共享位图,或者为每个实例分配一个新位图。
您可以使用静态 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
初始化。
以泛型类型声明的静态成员基本上是根据 class 及其泛型声明的。
例如 Foo<Bar>.baz
不等于 Foo<Qux>.baz
.
所以基本上你可以这样做:
abstract class Parent<T>
{
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 Parent : Parent<Parent>
{
Parent () : base()
{ }
}
class Subclass1 : Parent<Subclass1>
{
Subclass1() : base()
{ }
}
class Subclass2 : Parent<Subclass2>
{
Subclass2() : base()
{ }
}
void main()
{
Parent.pictureOrigin = Load("pictureForParent");
Parent<Subclass1>.pictureOrigin = Load("pictureForSubclass1");
Parent<Subclass2>.pictureOrigin = Load("pictureForSubclass2");
}
我有一个带有静态变量的基 class。我想创建派生的 subclasses,它会自动拥有自己的非共享静态变量。理想情况下它看起来像这样:
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
{
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
到每个子 class 并隐藏基础 class:
pictureOrigin
变量
class Subclass1 : Parent
{
new static Texture2D pictureOrigin;
Subclass1() : base()
{
picture = pictureOrigin;
}
}
或者,创建抽象方法或类似方法以确保在子classes 中创建新的静态变量。但这似乎太麻烦而且不太优雅。有更好的方法吗?
你的问题设计得很糟糕。在我看来,静态变量通常是不好的做法,适当的面向对象设计可以消除使用静态成员的需要。
像这样尝试重构:
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) {
}
}
让我详细说明为什么静态是一个糟糕的选择:
- 您的 class 现在仅适用于单个位图。消除了为多个位图重用 class 的可能性(这是您要反对的限制)
- 在调用静态 setter 之前,您的 class 未处于有效状态。通常,对象一旦构造,就应该处于有效状态。如果其他人正在使用您的对象,他们必须在 class. 上静态设置位图,这对其他人来说并不明显
- 破坏自然垃圾收集。例如,如果您希望在收集 SubClass 的所有实例时对 Texture2D 对象进行垃圾收集,那么它不适用于您的静态设计。或者,如果您使用 oop 设计(如建议的那样),您可以根据您的用例灵活地进行垃圾收集或不进行垃圾收集。
- 使线程更复杂。静态是全局的,所以你需要全局互斥锁来保证线程安全。
- 使测试更加困难。如果你想对 class 进行单元测试,你必须确保每次测试后静态都被清除,并且你不能 运行 针对这个 class 并行进行两个单元测试.
- 使内存管理不灵活。如果您使用面向对象的设计,您可以选择在所有实例之间共享位图,或者为每个实例分配一个新位图。
您可以使用静态 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
初始化。
以泛型类型声明的静态成员基本上是根据 class 及其泛型声明的。
例如 Foo<Bar>.baz
不等于 Foo<Qux>.baz
.
所以基本上你可以这样做:
abstract class Parent<T>
{
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 Parent : Parent<Parent>
{
Parent () : base()
{ }
}
class Subclass1 : Parent<Subclass1>
{
Subclass1() : base()
{ }
}
class Subclass2 : Parent<Subclass2>
{
Subclass2() : base()
{ }
}
void main()
{
Parent.pictureOrigin = Load("pictureForParent");
Parent<Subclass1>.pictureOrigin = Load("pictureForSubclass1");
Parent<Subclass2>.pictureOrigin = Load("pictureForSubclass2");
}