【问题标题】:Custom static variables for child classes子类的自定义静态变量
【发布时间】:2019-01-24 19:07:32
【问题描述】:

我有这样的事情:

class powerup {
public static int cooldown = 1;
}

class freeze : powerup {

//some unrelated code
}
class burn : powerup {

//unrelated
}

我想为冻结和燃烧通电的冷却时间设置不同的值,并且以静态方式,因为我无法在我设置冷却时间的地方实例化它们,而且拥有它们也更有意义静态的,因为它们是独一无二的。所以我觉得我需要用“new”覆盖冷却时间,但感觉不对。有什么我不知道的解决方案吗? 提前致谢

【问题讨论】:

  • 你不能实例化冻结或烧录?没有构造函数?
  • 我可以,但在我当前的代码库中没有任何意义(那些是用 Unity 和 MonoBehaviours 制作的)......我真的很想保持这部分静态,因为每种类型只有一个实例通电。
  • 如果它是使用 IOC 创建的,仍然会调用默认构造函数。你可以在里面添加初始化。

标签: c# inheritance static


【解决方案1】:

C# 中没有可覆盖性和静态性的组合;这些在某种意义上是对立的。

更好的技术是创建实例;如果有意义的话,这些实例可能是单例。我倾向于做类似的事情:

abstract class Powerup
{
  public virtual int Cooldown => 1
}

sealed class Freeze : Powerup
{
}

sealed class Burn : Powerup
{
  public override int Cooldown => 2;
}

但是当这些是单例时,我特别喜欢的一种技术是:

abstract class Powerup
{
  private Powerup() {} // Prevent instantiation

  public virtual int Cooldown => 1

  public static readonly Powerup Freeze = new FreezePower();
  private sealed class FreezePower : Powerup
  {
  }

  public static readonly Powerup Burn = new BurnPower();
  private sealed class BurnPower : Powerup
  {
    public override int Cooldown => 2;
  }
}

现在看使用现场:

Console.WriteLine(Powerup.Freeze.Cooldown); // 2

在我认为的使用站点上看起来非常好。

【讨论】:

    【解决方案2】:

    您可以使用new modifier隐藏子类的父属性,例如:

    class powerup
    {
        public static int cooldown = 1;
    }
    
    class freeze : powerup
    {
        public new static int cooldown = 3;
        //some unrelated code
    }
    class burn : powerup
    {
        public new static int cooldown = 2;
        //unrelated
    }
    

    这提供了以下结果:

    Console.WriteLine($"powerup: {powerup.cooldown}");
    Console.WriteLine($"freeze: {freeze.cooldown}");
    Console.WriteLine($"burn: {burn.cooldown}");
    

    【讨论】:

    • 如果你不想使用接口,这是要走的路。简单明了。
    • 是的,就我而言,这也许是最好的方法,但我发现需要为每个子类添加一个新的很容易出错。不管怎么说,还是要谢谢你 !也许我需要使用那个方法
    • 做出预测;你认为static void M<T>() where T : powerup { Console.WriteLine(T.cooldown);} ... M<burn>(); 是做什么的?现在试试看。你现在明白为什么这是一个坏主意了吗?
    【解决方案3】:

    我相信您想要更新特定通电的所有实例的冷却时间值。在那种情况下,我会使用这样的东西:

    interface IPowerup {
        int Cooldown { get; set; }
    }
    
    class Freeze : IPowerup {
        private static int _cooldown;
        public int Cooldown { get { return _cooldown } set { _cooldown = value; }
        public Freeze() { Cooldown = 1; }
    }
    
    class Burn : IPowerup {
        private static int _cooldown;
        public int Cooldown { get { return _cooldown } set { _cooldown = value; }
        public Burn() { Cooldown = 2; }
    }
    

    所以现在,如果你为一个通电设置冷却时间,你就设置了所有的值。

    您还可以取消构造函数并实例化通电并设置冷却时间,如下所示:

    var burnPowerup = new Burn { Cooldown = 2 };
    

    【讨论】:

    • OP 提到他们无法实例化
    • 我相信他的意思是不能在设置冷却时间的地方实例化它们。必须查看更多他的代码才能了解他的意思。现在我仔细观察了,我相信他想更新所有选择类型的通电的冷却时间。将修改我的答案。
    • 我真的很喜欢这种方法!我将以这种方式实现它并让您保持最新状态!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-05
    相关资源
    最近更新 更多