简体   繁体   中英

C# Inheritance and Member Hiding

I'm developing a 2D space-shooter in Unity game engine.

I have a base class containing the variables shared among all the enemy space ships and that base class contains functions that are meant to be called by every instance of the derived classes. Take this void Start() function for example:

Base Class

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

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

Derived Class

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

I think you get the idea. I want the common initalizations to be done in the base.Start() function and for the class-specific initalizations to be done in this Start() function. However, I get the warning:

Assets/Scripts/L1EnemyScript.cs(7,14): warning CS0108: L1EnemyScript.Start() hides inherited member EnemyBaseScript.Start() . Use the new keyword if hiding was intended

I lack experience in OOP and C#, so what is the correct way to do what I think? What does this warning mean and how can I do it right?

In C#, inheriting a function with the same function signature will hide the previous one.

Take the example from Microsoft's website :

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

However hiding the function is probably not what you want:

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
}

Instead what you could do is make your base function "virtual":

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

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

Then we can override it:

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

You need to tell the compiler that Start is supposed to be overridden:

protected virtual void Start () { ... }

and that you are in fact overriding it on purpose in your derived class:

protected override void Start ()  { ... }

See the documentation for virtual and override for reference; there is more information here .

You current code defines two separate Start methods which happen to share the same name but are not otherwise related.

In C#, methods/properties are non-virtual by default. You must declare the method/property virtual if you wish to override it in the subclass. If you do not then:

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

while

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

What you want is to make the method virtual in the base class and override it in the subclass

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM