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



首先,我知道你不能覆盖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,并且代码中的许多部分我需要能够在没有实例的情况下获取 EffectA.kDuration 或类似的东西。

您要查找的内容有点奇怪,但是将它们保持静态并提供新值/实现的一种选择是仅通过使用相同的名称来隐藏继承的成员:

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 中将有一个warning,但可以通过传递。 不确定是否可以与Unity3D MonoDevelop一起使用。

最新更新