C#继承和成员隐藏

时间:2014-02-24 21:02:09

标签: c# inheritance

我正在Unity游戏引擎中开发2D太空射击游戏。

我有一个基类,包含在所有敌方太空船中共享的变量,并且该基类包含要由派生类的每个实例调用的函数。以此void Start()函数为例:

基类

public class EnemyBaseScript : MonoBehaviour 
{
    // some public/protected variables here

    protected void Start () 
    {
         // some initializations shared among all derived classes
    }
.
.
.
}

派生类

public class L1EnemyScript : EnemyBaseScript 
{       
    // Use this for initialization
    void Start () 
    {
        base.Start ();  // common member initializations
        hp = 8;         // hp initialized only for this type of enemy
        speed = -0.02f; // so does speed variable
    }
}

我想你明白了。我希望在base.Start()函数中完成常见的初始化,并在此Start()函数中完成特定于类的初始化。但是,我收到了警告:

  

Assets / Scripts / L1EnemyScript.cs(7,14):警告CS0108:L1EnemyScript.Start()隐藏继承的成员EnemyBaseScript.Start()。如果要隐藏

,请使用new关键字

我缺乏OOP和C#的经验,那么按照我的想法做正确的方法是什么?这个警告意味着什么,我该怎么做?

3 个答案:

答案 0 :(得分:7)

在C#中,继承具有相同功能签名的函数将隐藏前一个。

Take the example from Microsoft's website

class Base
{
   public void F() {}
}
class Derived: Base
{
   public void F() {}      // Warning, hiding an inherited name
}

然而隐藏功能可能不是你想要的:

class Base
{
   public static void F() {}
}
class Derived: Base
{
   new private static void F() {}   // Hides Base.F in Derived only
}
class MoreDerived: Derived
{
   static void G() { F(); }         // Invokes Base.F
}

相反,你可以做的是使你的基本功能"虚拟":

public class EnemyBaseScript : MonoBehaviour 
{
    // some public/protected variables here

    public virtual void Start () 
    {
         // some initializations shared among all derived classes
    }
.
.
.
}

然后我们可以覆盖它:

public class L1EnemyScript : EnemyBaseScript 
{       
    // Use this for initialization
    public override void Start () 
    {
        base.Start ();  // common member initializations
        hp = 8;         // hp initialized only for this type of enemy
        speed = -0.02f; // so does speed variable
    }
}

答案 1 :(得分:5)

您需要告诉编译器应该覆盖Start

protected virtual void Start () { ... }

并且你实际上是在你的派生类中故意覆盖它:

protected override void Start ()  { ... }

请参阅virtualoverride的文档以供参考;有更多信息here

您当前的代码定义了两个独立的Start方法,这些方法碰巧共享相同的名称,但在其他方面没有相关性。

答案 2 :(得分:0)

在C#中,默认情况下方法/属性是非虚拟的。如果您希望在子类中virtual,则必须声明方法/属性override。如果你不这样做:

EnemyBaseScript s = new LIEnemyScript();
s.Start(); // calls EnemyBaseScript.Start()

,而

L1EnemyScript s = new L1EnemyScript();
s.Start(); // calls L1EnemyScript.Start()

你想要的是在基类中使方法虚拟化并在子类中重写它

class EnemyBaseScript
{
    protected virtual void Start()
    {
        //...
    }
}

class L1EnemyBaseScript : EnemyBaseScript
{
    protected override void Start()
    {
        base.Start();
        //...
    }
}