C# 中的方法隐藏
在上一章中,你学习了如何使用 virtual
和 override
关键字实现方法重写。在这里,你将学习如果我们在不使用这些关键字的情况下,仍在派生类中重新定义基类方法会发生什么?
请看以下示例。
示例:不使用 Virtual 和 Override 关键字重写方法
class Person
{
public virtual void Greet()
{
Console.WriteLine("Hi! I am a person.");
}
}
class Employee : Person
{
public override void Greet()
{
Console.WriteLine("Hello! I am an employee.");
}
}
如你所见,Greet()
方法在基类和派生类中都已定义,但没有使用 virtual
和 override
关键字。现在,请猜测以下程序的输出。
示例:方法隐藏
class Program
{
public static void Main()
{
Person p1 = new Person();
p1.Greet();
Person p2 = new Employee();
P2.Greet();
Employee emp = new Employee();
emp.Greet();
}
}
当你编译上述程序时,它将给出以下警告。
warning CS0108: 'Employee.Greet()' hides inherited member 'Person.Greet()'.
Use the new keyword if hiding was intended.
但是,上述程序将成功运行并给出以下输出。
输出
Hi! I am a person. Hello! I am an employee. Hello! I am an employee.
如你所见,Greet()
方法的调用不依赖于对象的类型。在这里,Employee.Greet()
隐藏了基类方法 Person.Greet()
。这在 C# 中称为方法隐藏(基类方法)。
使用 new 关键字隐藏方法
在派生类中使用 new
关键字来隐藏基类方法。当你重用第三方 API 且无法控制基类时,这将非常有用。
new
关键字不会给出上述警告。以下代码将给出相同的结果,但不会在编译时给出任何警告。
示例:new 关键字
class Person
{
public void Greet()
{
Console.WriteLine("I am a person!");
}
}
class Employee : Person
{
public new void Greet()
{
Console.WriteLine("I am the Manager!");
}
}
通过在派生类方法中使用 new
关键字,C# 将其视为派生类的新方法并隐藏基类方法。Employee.Greet()
将被视为一个新方法。
new
关键字保留了产生该输出的关系,但它抑制了警告。基类类型的变量继续访问基类的成员,派生类类型的变量继续首先访问派生类中的成员,然后考虑从基类继承的成员。
了解何时使用 override 和 new 关键字。