Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在C中重写派生类中的静态常量#_C#_Oop_Inheritance_Static - Fatal编程技术网

C# 在C中重写派生类中的静态常量#

C# 在C中重写派生类中的静态常量#,c#,oop,inheritance,static,C#,Oop,Inheritance,Static,首先,我知道不能重写C#中的静态属性或函数 这是我需要的 public abstract class Effect { public virtual const float duration = 1.0f; public void boo() { //do some stuff with duration } public void foo() { //do some other stuff with duration } }

首先,我知道不能重写C#中的静态属性或函数

这是我需要的

public abstract class Effect
{
   public virtual const float duration = 1.0f;

   public void boo() {
         //do some stuff with duration
   }

   public void foo() {
        //do some other stuff with duration
   }
 }

public class EffectA : Effect
{
    public override const float duration = 3.0f;
}
基类和派生类中还有一些其他的东西,但我遇到的问题是这个静态常量。我需要在没有实例的情况下从代码的其他部分引用它,例如EffectA.duration。函数/属性也可以,但如果是静态的,也不能重写它们

我见过类似的问题,但所有的答案似乎都涉及到非静态的解决方案,也就是说,与其将其作为静态函数,不如将其作为实例函数。在我的例子中,在我想要查询EffectA.duration的地方,不希望创建实例。另外,我不希望有一个实例变量,因为实际上这些类是Unity3D单行为,而拥有一个静态实例没有多大意义,因为有许多实例在不同的点被创建和销毁

如果我希望能够在boo中共享代码,并且仍然能够访问每个派生类的静态持续时间,那么理想的解决方法是什么

以下是当前代码相关部分的修改版本:

public abstract class Effect : MonoBehaviour
{
    public virtual float kDuration { get { return 1.0f; }}

    public float elapsed = 0.0f;

    // Use this for initialization
    protected virtual void Start()
    {
        elapsed = kDuration;
    }

    // Update is called once per frame
    protected virtual void FixedUpdate()
    {
        elapsed -= Time.fixedDeltaTime;
        if(elapsed <= 0) {
            Destroy(this);
        }

        _doEffect();
    }

    protected abstract void _doEffect();
}

public class EffectA : Effect
{
    public override float kDuration { get {return 3.0f; } }

    protected override void _doEffect()
    {
        //Some behavior
    }
}
公共抽象类效应:单一行为
{
公共虚拟浮点kDuration{get{return 1.0f;}}
公共浮动时间=0.0f;
//用于初始化
受保护的虚拟void Start()
{
已用时间=kDuration;
}
//每帧调用一次更新
受保护的虚拟void FixeUpdate()
{
已用-=时间。固定时间;

如果(经过您正在寻找的有点奇怪,但是保持它们静态并提供新值/实现的一个选项是只使用相同的名称隐藏继承的成员:

public abstract class Effect
{
    public const float duration = 1.0f;

    public static void boo()
    {
        // this prints 1.0f
        Console.WriteLine(duration);
    }
}

public class EffectA : Effect
{
    public new const float duration = 3.0f;

    public new static void boo()
    {
        // this prints 3.0f
        Console.WriteLine(duration);
    }
}
请注意,
new
关键字刚刚为您消除了编译器警告,使用相同的名称会导致隐藏

更新

根据您的评论,以下是如何避免重复,只需调用共享实现:

public abstract class Effect
{
    public const float duration = 1.0f;

    public static void boo(float val = duration)
    {
        // your complex shared implementation
        Console.WriteLine(val);
    }
}

public class EffectA : Effect
{
    public new const float duration = 3.0f;

    public new static void boo()
    {
        Effect.boo(duration);
    }
}

可以尝试此方法,但可能不是正确的方法:

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine(" duration from Effect " + Effect.duration);
        Console.WriteLine(" duration from EffectA " + EffectA.duration);
        Console.WriteLine(" duration from EffectB " + EffectB.duration);
        Console.Read();
    }
}

class Effect
{
    public const float duration = 1.0f;
}
class EffectA : Effect
{
    public const float duration = 3.0f;
}
class EffectB : Effect
{
}
结果应该是:

duration from Effect 1
duration from EffectA 3
duration from EffectB 1
Visual Studio 2015中将出现
警告
,但可以忽略。
不确定是否可以使用
Unity3D MonoDevelop

答案很简单-如果不涉及“非静态解决方案”,您就无法做到这一点。但是,您可以使非静态解决方案适用于您。问题是“您将如何使用它?”展示一些您希望如何使用它的代码。在C#中,类本身不是对象(只有类的实例是对象),想要“覆盖”任何静态成员是毫无意义的。但是,即使可以,您认为您会如何使用覆盖?您想要做什么,而仅仅通过隐藏是无法做到的(使用
public new const float duration=3.0f;
)基类成员:“我不喜欢使用静态实例变量”--我甚至不知道这意味着什么。“静态实例变量”到底是什么?我用更多的代码更新了这个问题,以展示我如何尝试使用它。“静态实例变量”是一个输入错误;我指的是实例变量。我不能使用重写的原因是我要共享的代码在基类Effect中,因此如果我将其设置为静态重写,则在Start()上方的代码中函数将始终使用基类效果的kDuration,而不是对象实际所属的类的kDuration函数的作用我正在尝试共享将使用特定对象类的持续时间的代码。因此实例函数需要访问静态变量,但实例函数应该使用属于实例所在类的静态变量。如果我只是将其作为重写并引用“持续时间”在基类中,它将是有效定义的持续时间,而不是所需类的持续时间更复杂,并且在多个位置使用持续时间,这需要将boo复制粘贴到每个派生类,对吗?如果我需要更改该行为,我需要在每个复制粘贴位置更改它。理想情况下,我可以共享代码,因为每个效果都是相同的。@StackedAE不一定。您可以重构将“共享”代码转换成一个可重用的方法,然后从派生类调用它。看看更新。所以在这种情况下,您还必须在每个派生类中定义一个新的静态void boo(),对吗?如果您碰巧只定义了一个新的持续时间,但忘了放置一个新的boo()在派生类中,持续时间字段将与派生类的实际行为不匹配,这似乎很危险。此外,如果我们在基类中有多个函数,我们希望共享该使用持续时间(在我的应用程序中实际就是这样),然后我们必须在每个派生类中为它们中的每一个创建一个虚拟重写函数。没有办法自动实现这一点吗?@StackedAE是的,如果您忘记定义一个,它将使用父级重写函数,如果成员不是静态的,也会使用父级重写函数。恐怕没有银弹来防止您忘记某些东西,尽管有单元测试可以帮助你。如果你想让事情保持简单,继承可能不是最好的主意。