4

我有一系列对象,我们称它们为建筑物,每个对象都共享某些对该建筑物而言是静态的属性,但对于每个建筑物而言却不同,例如价格。我认为实现这一点的最佳方法是创建一个具有共享价格属性的抽象超类并在每个子类中设置值,但我不知道如何让它工作。这是我尝试过的一个例子:

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;
    }
}

这适用于建筑,但如果我想在创建价格之前检查价格(检查玩家是否有足够的钱),那么它只会返回一个空值。我确信这是一个超级简单的修复,但我无法弄清楚。有什么帮助吗?

4

3 回答 3

8

有一个“不完整”但简单的解决方案值得考虑。如果您将基类定义为通用类,并且在派生类中将 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();
    }
}
于 2015-01-29T18:39:22.017 回答
5

不要使用static. 静态表示 Building 的所有实例都具有相同的值。派生类不会继承它自己的静态副本;但总是会修改基类静态。在您的设计中,价格和turnToMake 只有一个值。

这应该适合你:

public abstract class Buildings
{
  internal int price;
  internal int turnsToMake;
}

但是,现在大多数人都不喜欢使用字段,而是更喜欢属性。

public abstract class Buildings
{
  internal int Price { get; set; }
  internal int TurnsToMake { get; set; }
}
于 2013-02-09T09:16:37.413 回答
1

我想在创建它之前检查价格 […]

我想这就是您进入静态字段的方式;但是,静态行为和虚拟行为不能结合使用。也就是说,您必须为每个子类重新声明静态字段。否则,您的所有子类共享完全相同的字段并覆盖彼此的值。

另一种解决方案是使用.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)。

(由于多态性,您可以拥有这样的“惰性工厂”的完整集合,并根据每个工厂的元数据找到要实例化的建筑类型。)

于 2013-02-09T09:17:57.720 回答