我正在学习C#,我遇到了以下问题。我有两个类:base和derived:
class MyBase
{
public void MyMethod()
{
Console.WriteLine("MyBase::MyMethod()");
}
}
class MyDerived: MyBase
{
public void MyMethod()
{
Console.WriteLine("MyDerived::MyMethod()");
}
}
目前,没有virtual
和override
关键字。当我编译它时,我得到警告(当然是预期的),我试图隐藏MyMethod
类MyBase
。
我想要做的是从具有派生类实例的基类调用该方法。我是这样做的:
MyDerived myDerived = new MyDerived();
((MyBase)myDerived).MyMethod();
当我在方法中未指定任何virtual
等关键字时,它可以正常工作。我试着把关键字组合起来,得到了以下结果:
| MyBase::MyMethod | MyDerived::MyMethod | Result printed on the console |
| -----------------|---------------------|-------------------------------|
| - | - | MyBase::MyMethod() |
| - | new | MyBase::MyMethod() |
| virtual | new | MyBase::MyMethod() |
| virtual | override | MyDerived::MyMethod() |
我希望你的表格清楚。 我有两个问题:
((MyBase)myDerived).MyMethod();
)调用函数是否正确?我知道base
关键字,但只能从派生类的内部调用它。是不是?virtual
和override
修饰符)调用的方法来自派生类?你能解释一下吗?答案 0 :(得分:18)
当您在覆盖该方法的类型实例上调用virtual
方法时,即使您转换为基类,也会始终调用被覆盖的版本。
在覆盖该方法的类上调用虚方法的基本实现的唯一方法是在使用base
关键字调用该方法的派生类(而不是基类)中创建第二个方法
一般来说,需要这样做是API设计不佳的标志 - 如果您认为需要调用基本版本,派生版本可能应该有不同的名称。
答案 1 :(得分:3)
至于你的第二个问题,你不是要改变你引用的对象的类型,而是改变你引用它的接口。因此,如果你有一个继承自A并覆盖函数C的对象B,即使你将B称为A,它仍然会调用派生类型最多的实现,在本例中为B.
答案 2 :(得分:2)
你是对的 - base
只能在派生类中调用 - Source。
此页面还提供了如何覆盖基类定义的示例。
答案 3 :(得分:2)
base
指的是给定实例的基类。顺便说一句,尽量避免编写强制执行替换原则的代码,换句话说,不要编写依赖于类层次结构实现的代码,因为如果添加新代码,则必须修改此代码派生类到你的基类。