在 .NET(C#)中,父类中的 virtual 方法和普通的公共方法(public 方法)在行为上有显著的区别,特别是在继承和多态场景下。
1.virtual方法
- 定义: virtual 方法是指父类中声明的方法,允许子类通过 override 关键字进行重写。
- 特点:动态绑定:virtual 方法支持运行时的多态性,也就是动态绑定。当通过父类引用或指针调用子类重写的 virtual 方法时,实际执行的是子类的重写版本,而不是父类的版本。重写(override):子类可以通过 override 关键字来提供不同的实现。运行时行为:当父类引用指向子类对象时,通过父类引用调用的方法将是子类重写的方法,而不是父类的实现。
示例:
class Parent
{
public virtual void Display()
{
Console.WriteLine("Parent Display");
}
}
class Child : Parent
{
public override void Display()
{
Console.WriteLine("Child Display");
}
}
Parent parent = new Child();
parent.Display(); // 输出: Child Display
2. 公共方法(普通public方法)
- 定义: 公共方法是普通的成员方法,它们不能被子类重写(除非它们是 virtual、abstract 或 override)。
- 特点:静态绑定:公共方法使用编译时的静态绑定,也称为早期绑定。调用的版本在编译时确定,而不是在运行时动态决定。不能重写:如果父类中的公共方法没有声明为 virtual,则子类不能通过 override 来提供新的实现。编译时行为:通过父类引用调用的方法始终是父类的版本,无论引用的实际对象类型是什么。
示例:
class Parent
{
public void Display()
{
Console.WriteLine("Parent Display");
}
}
class Child : Parent
{
public new void Display() // 这是隐藏父类方法,而非重写
{
Console.WriteLine("Child Display");
}
}
Parent parent = new Child();
parent.Display(); // 输出: Parent Display
3.new关键字隐藏父类方法
当父类中没有声明 virtual 方法,但子类想要提供不同的实现时,可以使用 new 关键字隐藏父类的方法。注意这不是重写,只是隐藏了父类的方法,具体调用哪个版本仍然依赖于引用的类型。
示例:
class Parent
{
public void Display()
{
Console.WriteLine("Parent Display");
}
}
class Child : Parent
{
public new void Display()
{
Console.WriteLine("Child Display");
}
}
Child child = new Child();
child.Display(); // 输出: Child Display
Parent parent = new Child();
parent.Display(); // 输出: Parent Display
主要区别总结:
- 多态性:
- virtual 方法支持运行时多态,子类可以通过 override 提供不同实现,运行时根据对象实际类型决定调用的版本。
- 普通 public 方法不支持多态性,方法调用是静态绑定,调用的版本在编译时确定。
- 重写:
- virtual 方法允许子类重写。
- 普通 public 方法不能被重写,只能被隐藏(通过 new 关键字)。
- 调用方式:
- 通过父类引用或对象调用 virtual 方法时,会根据对象的实际类型执行重写后的方法。
- 通过父类引用调用普通 public 方法时,执行的始终是父类版本的方法。