解释继承方法重写

本文关键字:重写 方法 继承 解释 | 更新日期: 2023-09-27 18:35:42

这里有两个类:

public class ClassA
{
    public string result()
    {
        return "ClassA_Result";
    }
}

public class ClassB : ClassA
{
    public string result()
    {
        return "ClassB_Result";
    }
}

当我创建 ClassB 的实例时,我得到的结果是 ClassB_Result .我希望结果会ClassA_Result

 ClassB objB = new ClassB();
 string b = objB.result();    //result is `ClassB_Result`

解释继承方法重写

首先,你没有覆盖result()方法——事实上你不能,因为它不是虚拟的。

编译器应该给你一个这样的警告:

警告 CS0108: "ClassB.result()" 隐藏继承的成员 'ClassA.result()'。如果要隐藏,请使用 new 关键字。

始终阅读编译器警告。他们在那里帮助你。

您应该在 ClassA 中对方法有一个 virtual 修饰符,在 ClassB 中对方法有一个override修饰符。我还鼓励您遵循 .NET 命名约定 - 我知道这只是一个示例,但即使在虚拟代码中也值得遵循约定。(result应该是Result

现在,即使您已经像这样修复了代码,您仍然会得到ClassB_Result - 因为您正在创建ClassB的实例。如果你写:

ClassA objB = new ClassB();
string b = objB.result();

使用该代码片段,在当前代码中,它将给出ClassA_Result的结果,因为该方法不是虚拟调用的。使用固定代码,它将给出ClassB_Result的结果,因为将调用 ClassB 中的覆盖。目前,您在ClassA中的方法完全无关紧要,因为objB的编译时类型是 ClassB

或者在 B 类中使用 new 关键字

    public class ClassB : ClassA
    {
        new public string result()
        {
            return "ClassB_Result";
        }
    }

来自 MSDN -"用作声明修饰符时,new 关键字显式隐藏从基类继承的成员。隐藏继承的成员时,成员的派生版本将替换基类版本。尽管可以在不使用新修饰符的情况下隐藏成员,但会收到编译器警告。如果使用 new 显式隐藏成员,则会禁止显示此警告。http://msdn.microsoft.com/en-us/library/435f1dw2.aspx

你所做的是方法隐藏而不是方法覆盖,

使用带有方法隐藏的A类和B类的定义,下面的代码将得到"ClassB_Result"

ClassB objB = new ClassB();
string b = obj.result(); 

但下面会得到"ClassA_Result"

ClassA obj = new ClassB();
string a = obj.result(); 

但是对于方法重写,您的类定义需要稍微更改一下,在类 A 中,方法应标记为"虚拟",而在类 B 中,相同的方法应标记为覆盖。

使用方法覆盖时,下面的两个代码片段将仅获得"ClassB_Result"。

ClassB objB = new ClassB();
string b = obj.result(); 

ClassA obj = new ClassB();
string a = obj.result();