C#中虚方法,抽象方法和隐藏方法

虚方法:
即为基类中定义的允许在派生类中重写的方法,使用virtual关键字定义。如:

public virtual void EatFood()
{
    Console.WriteLine("Animal吃东西");
}

注意:虚方法也可以被直接调用。如:

Animal a = new Animal();
a.EatFood();

执行输出结果为:

Animal吃东西

抽象方法:
在基类中定义的并且必须在派生类中重写的方法,使用 abstract 关键字定义。如:

public abstract class Biology
{
    public abstract void Live();
}
public class Animal : Biology
{
    public override void Live()
    {
        Console.WriteLine("Animal重写的抽象方法");
        //throw new NotImplementedException();
    } 
}

注意:抽象方法只能在抽象类中定义,如果不在抽象类中定义,则会报出如下错误:
在这里插入图片描述
虚方法和抽象方法的区别
1.虚方法必须有实现部分,抽象方法没有提供实现部分,抽象方法是一种强制派生类覆盖的方法,否则派生类将不能被实例化。
2.抽象方法只能在抽象类中声明,虚方法不是。如果类包含抽象方法,那么该类也是抽象的,也必须声明类是抽象的。
3.抽象方法必须在派生类中重写,这一点和接口类似,虚方法不需要再派生类中重写。
简单说,抽象方法是需要子类去实现的。虚方法是已经实现了的,可以被子类覆盖,也可以不覆盖,取决于需求。

抽象方法和虚方法都可以供派生类重写。

虚方法的调用:调用上,使用子类构造的对象调用虚方法,就会调用子类的方法,使用父类构造的对象,就会调用父类的方法。

隐藏方法的调用:调用上, 使用子类类型的声明调用隐藏方法,就会调用到子类的方法。若想调用被隐藏的方法,需要用父类类型的声明来调用。

隐藏方法:
在派生类中定义的和基类中的某个方法同名的方法,使用 new 关键字定义。如在基类 Animal 中有一方法 Sleep():

public void Sleep()
{
    Console.WriteLine("Animal Sleep");
}

则在派生类 Cat 中定义隐藏方法的代码为:

new public void Sleep()
{
    Console.WriteLine("Cat Sleep");
}

或者为:

public new void Sleep()
{
    Console.WriteLine("Cat Sleep");
} 

注意:

(1)隐藏方法不但可以隐藏基类中的虚方法,而且也可以隐藏基类中的非虚方法。
(2)隐藏方法中父类的实例调用父类的方法,子类的实例调用子类的方法。
(3)和上一条对比:重写方法中子类的变量调用子类重写的方法,父类的变量要看这个父类引用的是子类的实例还是本身的实例,如果引用的是父类的实例那么调用基类的方法,如果引用的是派生类的实例则调用派生类的方法。

隐藏方法和虚方法调用范例:

using System;

namespace ConsoleApp1
{
    class Program
    {
        static void Main(string[] args)
        {
            //---- 隐藏方法的调用----begin
            //隐藏方法的调用:调用上, 使用子类类型的声明调用隐藏方法,就会调用到子类的方法。若想调用被隐藏的方法,需要用父类类型的声明来调用。

            Boss oneEnemy = new Boss(); 
            oneEnemy.Move(); // 调用的是隐藏方法, 用子类的声明来调用的,调用的就是子类的Move。

            Enemy twoEnemy = new Boss();
            twoEnemy.Move(); // 调用的隐藏方法, 用父类的声明来调用的,调用的就是父类的Move方法。
                             //-----------------------end

            //-----虚方法的调用----- begin
            //用什么类型 来构造,在调用方法的时候就会调用什么类型的方法。
            //虚方法的调用:调用上,使用子类构造的对象调用虚方法,就会调用子类的方法,使用父类构造的对象,就会调用父类的方法。

            Enemy threeEnemy = new Enemy();
            threeEnemy.Attack(); // 调用虚方法,用父类来实例化的,所以调用的是父类的Attac方法。

            Enemy fourEnemy = new Boss();
            fourEnemy.Attack();  // 调用虚方法,用子类来实例化的,所以调用的就是子类(Boss)的Attac方法。

            //-----虚方法的调用------end

            Console.ReadKey();
        }

        

       

        class Enemy
        {
            public void Move()
            {
                Console.WriteLine("调用了 enemy的move方法");
            }
            public virtual void Attack()
            {
                Console.WriteLine("enemy attac");
            }
        }


        class Boss : Enemy
        {
            public override void Attack()
            {
                Console.WriteLine("Boss Attac");
            }

            public new void Move()
            {
                Console.WriteLine("Boss move");
            }
        }

    }
}

C# 多态性

原文地址:https://www.cnblogs.com/LcVong/p/13609248.html