C#继承和成员隐藏
我正在Unity游戏引擎中开发一个2D太空射击游戏 我有一个基类,包含所有敌方太空船共享的变量,该基类包含的函数将由派生类的每个实例调用。以这个C#继承和成员隐藏,c#,inheritance,C#,Inheritance,我正在Unity游戏引擎中开发一个2D太空射击游戏 我有一个基类,包含所有敌方太空船共享的变量,该基类包含的函数将由派生类的每个实例调用。以这个void Start()函数为例: 基类 public class EnemyBaseScript : MonoBehaviour { // some public/protected variables here protected void Start () { // some initializati
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
}
}
派生类
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()
。如果要隐藏,请使用新关键字
我缺乏OOP和C#方面的经验,那么我认为正确的方法是什么呢?此警告是什么意思?如何正确执行此警告?您需要告诉编译器应该覆盖
Start
:
protected virtual void Start () { ... }
事实上,您在派生类中有意重写它:
protected override void Start () { ... }
参见文件以获取参考;还有更多的信息
当前代码定义了两个独立的Start
方法,它们恰好共享相同的名称,但在其他方面没有关联。在C#中,继承具有相同函数签名的函数将隐藏上一个函数
:
但是,隐藏函数可能不是您想要的:
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 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
}
}
在C#中,默认情况下方法/属性是非虚拟的。如果希望在子类中重写方法/属性,则必须声明该方法/属性virtual
。如果没有,则:
EnemyBaseScript s = new LIEnemyScript();
s.Start(); // calls EnemyBaseScript.Start()
当
您想要的是使方法在基类中成为虚拟的,并在子类中重写它
class EnemyBaseScript
{
protected virtual void Start()
{
//...
}
}
class L1EnemyBaseScript : EnemyBaseScript
{
protected override void Start()
{
base.Start();
//...
}
}
嗯。我一直认为,
虚拟
函数是空的,以后可以通过重写
来填充,我认为,这会完全重写虚拟函数(忽略其中的内容),并使以前在虚拟函数中编写的代码变得无关。现在我了解到它是对基本Start()
的一种扩展,这非常好,正是我所需要的。如果我弄错了,请纠正我,谢谢你的回答。@Varaquilex:重写一个方法会使被重写的代码变得不相关(除非你在重写中调用base.Start
)。为什么您认为它在扩展?噢,即使我们重写它,我调用函数(base.start()
)的方式也会触发以前编写的代码。我认为这是不可能的后,压倒它。现在一切都清楚了:)不,瓦拉奎莱克斯。这些都是抽象的成员。我浏览了互联网,你简洁的例子是唯一能让我“点击”的东西。非常感谢。
class EnemyBaseScript
{
protected virtual void Start()
{
//...
}
}
class L1EnemyBaseScript : EnemyBaseScript
{
protected override void Start()
{
base.Start();
//...
}
}