• 友链

  • 首页

  • 文章归档
h u a n b l o g
h u a n b l o g

欢

HI,Friend

04月
12
C#

虚方法与覆写方法

发表于 2022-04-12 • 字数统计 4224 • 被 1,404 人看爆

概念

在派生类中重写基类方法

规则

  • 派生类的方法和基类的方法有相同的签名和返回类型。
  • 基类的方法使用virtual标注。
  • 派生类的方法使用override标注。

例

class MyBaseClass
    {
        virtual public void Print()     //基类
        {
            Console.WriteLine("基类");
        }
    }

    class MyDerivedClass:MyBaseClass    //派生类
    {
        override public void Print()
        {
            Console.WriteLine("派生类");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            MyDerivedClass derived = new MyDerivedClass();
            MyBaseClass mybc = (MyBaseClass)derived;        //转换成基类
            derived.Print();        //从派生类部分调用Print
            mybc.Print();           //从基类部分调用Print
            Console.ReadKey();

        }
    }

结果

派生类
派生类

分析

当使用基类引用(mybc)调用Print方法时,方法调用被传递到派生类并执行,因为:

  • 基类的方法被标记为virtual;
  • 在派生类中有匹配的override方法。
    虚方法与覆写方法.png

注意

  • 覆写和被覆写的方法必须有相同的可访问性。换一种说法,被覆写的方法不能是private等,而覆写方法是public。
  • 不能覆写static方法或非虚方法。
  • 方法、属性和索引器,以及另一种成员类型事件,都可以被声明为virtual和override。

覆写标记为override的方法

override可以为另一个override方法进行重写

规则

  • 当使用对象基类部分的引用调用一个覆写的方法时,方法的调用被沿派生层次上溯执行,一直到标记为override的方法的最高派生版本。
  • 如果在更高的派生级别有该方法的其他声明,但没有被标记为override,那么它们不会被调用。

1.使用override声明Print


class MyBaseClass
{
    virtual public void Print()
    {
        Console.WriteLine("基类");
    }
}

class MyDerivedClass:MyBaseClass
{
    override public void Print()
    {
        Console.WriteLine("派生类");
    }
}

class SecondDerived:MyDerivedClass      //最高派生类
{
    public override void Print()
    {
        Console.WriteLine("派生类2");
    }
}

class Program
{
    static void Main(string[] args)
    {
        SecondDerived derived = new SecondDerived();
        MyBaseClass mybc = (MyBaseClass)derived;        //转换成基类
        derived.Print();        //从派生类部分调用Print
        mybc.Print();           //从基类部分调用Print
        Console.ReadKey();

    }
}

结果

派生类2
派生类2

分析

SecondDerived的Print方法声明为override,那么它会覆盖方法全部两个低级派生类别版本
如果一个基类的引用被用于调用Print,它会向上传递通过整个链达到类SecondDerived中实现
override覆写方法.png
两条语句中的第一条使用最高派生类SecondDerived的引用调用Print方法。这不是通过基类部分的引用的调用,所以它将会调用SecondDerived中实现的方法。
而第二条语句使用基类MyBaseClass的引用调用Print方法。

2.使用new声明Print

使用new屏蔽基类方法

class SecondDerived:MyDerivedClass      //最高派生类
{
    public new void Print()
    {
        Console.WriteLine("派生类2");
    }
}

class Program
{
    static void Main(string[] args)
    {
        SecondDerived derived = new SecondDerived();
        MyBaseClass mybc = (MyBaseClass)derived;        //转换成基类
        derived.Print();        //从派生类部分调用Print
        mybc.Print();           //从基类部分调用Print
        Console.ReadKey();

    }
}

结果

派生类2
派生类

分析

当方法Print通过SecondDerived的引用调用时,SecondDerived中的方法被执行
当方法通过NyBaseClass的引用调用时,方法调用只向上传递了一级,到达类MyDerived,在那里它被执行。
隐藏覆写方法.png

覆盖其他成员

class MyBaseClass
{
    private int _myInt = 5;
    virtual public int MyProperty
    {
        get
        {
            return _myInt;
        }
    }
}

class MyDerivedClass:MyBaseClass
{
    private int _myInt = 10;
    override public int MyProperty
    {
        get
        {
            return _myInt;
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        MyDerivedClass derived = new MyDerivedClass();
        MyBaseClass mybc = (MyBaseClass)derived;        //转换成基类
        Console.WriteLine($"derived.MyProperty:{derived.MyProperty}");
        Console.WriteLine($"mybc.MyProperty:{mybc.MyProperty}");
        Console.ReadKey();

    }
}

结果

derived.MyProperty:10
mybc.MyProperty:10

不推荐在构造函数中调用虚方法

分享到:
程序集间继承
C#中派生类继承基类操作
  • 文章目录
  • 站点概览
欢

网红 欢

你能抓到我么?

Email RSS
看爆 Top5
  • mac系统版本与Xcode版本有冲突 4,091次看爆
  • JAVA_HOME环境配置问题 3,741次看爆
  • AssetBundle使用 3,509次看爆
  • VSCode配置C++开发环境 3,264次看爆
  • Lua反射 3,141次看爆

Copyright © 2025 欢 粤ICP备2020105803号-1

由 Halo 强力驱动 · Theme by Sagiri · 站点地图