我有一系列对象,让我们称之为建筑,每个对象共享特定的属性,这些属性对于该建筑是静态的,但对于每个建筑都不同,例如价格。我认为实现这一点的最佳方法是创建一个具有shared-price属性的抽象超类,并在每个子类中设置值,但我不知道如何实现。下面是我尝试过的一个例子:
using System;
public abstract class Buildings
{
internal static int price;
internal static int turnsToMake;
}
using System;
public class Walls : Buildings
{
public Walls()
{
price = 200;
turnsToMake = 5;
}
}
这对构建来说很好,但如果我想在创建它之前检查价格(检查玩家是否有足够的钱),那么它只会返回一个空值。我确信这是一个超级简单的解决方案,但我想不通。有什么帮助吗?
有一个"不完整"但简单的解决方案值得考虑。如果您将基类定义为Generic类,并且在派生类中将T设置为类本身,则它将起作用。
之所以会出现这种情况,是因为.NET为每个新定义静态地定义了一个新类型。
例如:
class Base<T>
{
public static int Counter { get; set; }
public Base()
{
}
}
class DerivedA : Base<DerivedA>
{
public DerivedA()
{
}
}
class DerivedB : Base<DerivedB>
{
public DerivedB()
{
}
}
class Program
{
static void Main(string[] args)
{
DerivedA.Counter = 4;
DerivedB.Counter = 7;
Console.WriteLine(DerivedA.Counter.ToString()); // Prints 4
Console.WriteLine(DerivedB.Counter.ToString()); // Prints 7
Console.ReadLine();
}
}
不要使用static
。Static表示Building的所有实例都具有相同的值。派生类不会继承它自己的静态副本;但是总是修改基类静态。在你的设计中,只有一个性价比和转折点ToMake。
这应该对你有用:
public abstract class Buildings
{
internal int price;
internal int turnsToMake;
}
然而,现在大多数人不喜欢使用字段,而更喜欢属性。
public abstract class Buildings
{
internal int Price { get; set; }
internal int TurnsToMake { get; set; }
}
我想在创建之前检查价格[…]
我想这就是得到静态场的方法;然而,静态行为和虚拟行为不能结合在一起。也就是说,您必须为每个子类重新声明静态字段。否则,所有子类共享完全相同的字段,并覆盖彼此的值。
另一种解决方案是使用.NET(4或更高版本)框架类库中的Lazy<T, TMetadata>
类型:
public class Cost
{
public int Price { get; set; }
public int TurnsToMake { get; set; }
}
var lazyBuildings = new Lazy<Buildings, Cost>(
valueFactory: () => new Walls(),
metadata: new Cost { Price = 200, TurnsToMake = 5 });
if (lazyBuildings.Metadata.Price < …)
{
var buildings = lazyBuildings.Value;
}
也就是说,元数据(.Metadata
)现在位于实际类型(Buildings
、Walls
)之外,可以用来决定是否真的要构建它的实例(.Value
)
(由于多态性,您可以拥有一整套这样的"懒惰工厂",并根据每个工厂的元数据找到要实例化的构建类型。)
基于Uri Abramson的回答:
如果需要从基类中访问静态属性,请使用反射从T
中获取值。此外,您可以强制要求必须使用派生类型的T
继承Base
。
例如
class Base<T> where T : Base <T> {
static int GetPropertyValueFromDerivedClass<PropertyType>(BindingFlags Flags = BindingFlags.Public | BindingFlags.Static, [CallerMemberName] string PropertyName = "")
{
return typeof(T).GetProperty(PropertyName, Flags)?.GetValue(null);
}
static int Counter{ get => GetPropertyValueFromDerivedClass(); }
}
static int DoubleCounter{ return Counter*2; } //returns 8 for DerivedA and 14 for DerivedB
}
如果你有更好的方法,请发帖。
对继承人来说不是那么容易,但可行。。。
public abstract class BaseType
{
public abstract contentType Data { get; set; }
}
public class InheritedType : BaseType
{
protected static contentType _inheritedTypeContent;
public override contentType Data { get => _inheritedTypeContent; set => _inheritedTypeContent = value; }
}