C#(十八)之C#虚方法virtual

本文涉及的产品
模型训练 PAI-DLC,5000CU*H 3个月
模型在线服务 PAI-EAS,A10/V100等 500元 1个月
交互式建模 PAI-DSW,每月250计算时 3个月
简介: C#中的继承,C#是面向对象语言,面向对象三种特性:封装、继承、多态。这里主要是继承,本篇只是基础。

QQ图片20220426110546.jpg

C#中的继承,C#是面向对象语言,面向对象三种特性:封装、继承、多态。


这里主要是继承,这篇只是基础


首先定义一个基类:积累中含有一个使用virtual定义的一个虚方法。 virtual关键字用于在基类中修饰方法。


一、virtual的使用会有两种情况:


1、在基类中定义了virtual方法,但在派生类中没有重写该虚方法。那么在对派生类实例的调用中,该虚方法使用的是基类定义的方法。


2、在基类中定义了virtual方法,然后在派生类中使用override重写该方法。那么在对派生类实例的调用中,该虚方法使用的是派生重写的方法。


二、virtual用虚方法标记:


a、可在派生类中以override覆盖此方法


b、不覆盖也可由对象调用


c、无此标记的方法(也无其他标记),重写时需用new隐藏原方法


实例:


class Program
    {
        static void Main(string[] args)
        {
            A a;         // 定义一个a这个A类的对象.这个A就是a的申明类
            A b;         // 定义一个b这个A类的对象.这个A就是b的申明类
            A c;         // 定义一个c这个A类的对象.这个A就是b的申明类
            A d;         // 定义一个d这个A类的对象.这个A就是b的申明类
            a = new A(); // 实例化a对象,A是a的实例类
            b = new B(); // 实例化b对象,B是b的实例类
            c = new C(); // 实例化b对象,C是b的实例类
            d = new D(); // 实例化b对象,D是b的实例类
            a.Func();    // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A
            b.Func();    // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B
            c.Func();    // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B
            d.Func();    // 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A
            D d1 = new D();
            d1.Func(); // 执行D类里的Func(),输出结果 Func In D
            Console.ReadLine();
        }
    }
    class A
    {
        public virtual void Func() // 注意virtual,表明这是一个虚拟函数
        {
            Console.WriteLine("Func In A");
        }
    }
    class B : A // 注意B是从A类继承,所以A是父类,B是子类
    {
        public override void Func() // 注意override ,表明重新实现了虚函数
        {
            Console.WriteLine("Func In B");
        }
    }
    class C : B // 注意C是从A类继承,所以B是父类,C是子类
    {
    }
    class D : A // 注意B是从A类继承,所以A是父类,D是子类
    {
        public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现
        {
            Console.WriteLine("Func In D");
        }
    }


三、重载和重写的区别:


重写:通常,派生类继承基类的方法。因此,在调用对象继承方法的时候,调用和执行的是基类的实现。但是,有时需要对派生类中的继承方法有不同的实现。例如,假设动物类存在“跑"的方法,从中派生出马和狗,马和狗的跑得形态是各不相同的,因此同样方法需要两种不同的实现,这就需要"重新编写"基类中的方法。"重写"基类方法就是修改它的实现或者说在派生类中重新编写。


重载:在一个类中用相同的名称但是不同的参数类型创建一个以上的过程、实例构造函数或属性。


QQ图片20220426120714.png


// 这里是重载
 class Program  
    {  
        static void Main(string[] args)  
        {  
            string s = null;  
            show(s);  
            object a = "123";  
            show(a);  
        }  
            static void show(string s)  
            {  
                Console.WriteLine("string");  
           }  
           static void show(object o)  
           {  
               Console.WriteLine("object");  
           }  
       }  
class tarce {
        public void setWidth(int w)
        {
            width = w;
        }
        public void setHeight(int h)
        {
            height = h;
        }
        protected int width;
        protected int height;
        // Virtual虚方法
        public virtual string GetResult()
        {
            return "我是一个虚方法";
        }
    }


定义一个派生类:继承了基类


class paisheng : tarce {
        public int getArea()
        {
            return (width * height);
        }
        // 在派生类中重写Virtual虚方法
        public override string GetResult()
        {
            return "我是在派生类中重写的虚方法";
        }
    }


调用以上两个类:


class Program
    {
        /* C#主要的运行函数,就是main函数 */
        static void Main(string[] args)
        {
            paisheng pai = new paisheng();
            pai.setWidth(12);
            pai.setHeight(9);
            int area = pai.getArea();
            Console.WriteLine(area);
            string str = pai.GetResult();
            Console.WriteLine(str);
        }
    }


这里再墨迹一下:


Private:私有变量,只能自己调用,你儿子只能是你儿子

Protected:受保护的变量,你大爷永远是你大爷,但他也可能是别人的大爷。

Public:公共变量,公共电话,谁都能打。


测试使用全部代码:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace @virtual
{
    class Program
    {
        static void Main(string[] args)
        {
            paisheng pai = new paisheng();
            pai.setWidth(12);
            pai.setHeight(9);
            int area = pai.getArea();
            Console.WriteLine(area);
            string str = pai.GetResult();
            Console.WriteLine(str);
            Console.WriteLine("======================================================================");
            A a;         // 定义一个a这个A类的对象.这个A就是a的申明类
            A b;         // 定义一个b这个A类的对象.这个A就是b的申明类
            A c;         // 定义一个c这个A类的对象.这个A就是b的申明类
            A d;         // 定义一个d这个A类的对象.这个A就是b的申明类
            a = new A(); // 实例化a对象,A是a的实例类
            b = new B(); // 实例化b对象,B是b的实例类
            c = new C(); // 实例化b对象,C是b的实例类
            d = new D(); // 实例化b对象,D是b的实例类
            a.Func();    // 执行a.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类A,就为本身 4.执行实例类A中的方法 5.输出结果 Func In A
            b.Func();    // 执行b.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类B,有重载的 4.执行实例类B中的方法 5.输出结果 Func In B
            c.Func();    // 执行c.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类C,无重载的 4.转去检查类C的父类B,有重载的 5.执行父类B中的Func方法 5.输出结果 Func In B
            d.Func();    // 执行d.Func:1.先检查申明类A 2.检查到是虚拟方法 3.转去检查实例类D,无重载的(这个地方要注意了,虽然D里有实现Func(),但没有使用override关键字,所以不会被认为是重载) 4.转去检查类D的父类A,就为本身 5.执行父类A中的Func方法 5.输出结果 Func In A
            D d1 = new D();
            d1.Func(); // 执行D类里的Func(),输出结果 Func In D
            Console.ReadLine();
        }
    }
    // 这是基类
    class tarce
    {
        public void setWidth(int w)
        {
            width = w;
        }
        public void setHeight(int h)
        {
            height = h;
        }
        protected int width;
        protected int height;
        // Virtual虚方法
        public virtual string GetResult()
        {
            return "我是一个虚方法";
        }
    }
    // 这是派生类
    class paisheng : tarce
    {
        public int getArea()
        {
            return (width * height);
        }
        // 在派生类中重写Virtual虚方法
        public override string GetResult()
        {
            return "我是在派生类中重写的虚方法";
        }
    }
    class A
    {
        public virtual void Func() // 注意virtual,表明这是一个虚拟函数
        {
            Console.WriteLine("Func In A");
        }
    }
    class B : A // 注意B是从A类继承,所以A是父类,B是子类
    {
        public override void Func() // 注意override ,表明重新实现了虚函数
        {
            Console.WriteLine("Func In B");
        }
    }
    class C : B // 注意C是从A类继承,所以B是父类,C是子类
    {
    }
    class D : A // 注意B是从A类继承,所以A是父类,D是子类
    {
        public new void Func() // 注意new ,表明覆盖父类里的同名类,而不是重新实现
        {
            Console.WriteLine("Func In D");
        }
    }
}



相关实践学习
使用PAI-EAS一键部署ChatGLM及LangChain应用
本场景中主要介绍如何使用模型在线服务(PAI-EAS)部署ChatGLM的AI-Web应用以及启动WebUI进行模型推理,并通过LangChain集成自己的业务数据。
机器学习概览及常见算法
机器学习(Machine Learning, ML)是人工智能的核心,专门研究计算机怎样模拟或实现人类的学习行为,以获取新的知识或技能,重新组织已有的知识结构使之不断改善自身的性能,它是使计算机具有智能的根本途径,其应用遍及人工智能的各个领域。 本课程将带你入门机器学习,掌握机器学习的概念和常用的算法。
目录
相关文章
|
3月前
|
C# 索引
C#中的virtual和override关键字
C#中的virtual和override关键字
45 3
|
6月前
|
C# 索引
C#学习相关系列之abstract和virtual用法
C#学习相关系列之abstract和virtual用法
C#学习virtual(虚拟的)和abstract(抽象的)的区别
C#学习virtual(虚拟的)和abstract(抽象的)的区别
115 0
C#中抽象方法与虚方法的区别
C#中抽象方法与虚方法的区别
|
C#
C# 虚方法(virtual)案例详解
C# 虚方法(virtual)案例详解
201 3
|
测试技术 C#
C#语法-虚方法详解 Virtual 虚函数
虚方法 / Virtual 本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) Chinar —— 心...
1154 0
|
C#
C#虚方法
如果说在一个类中已经使用了一个方法而且已经实现,而我想在它的子类中也想使用这个方法,而且也想实现   就像下面这种样子--但是现在还不能用 using System; using System.
805 0
|
C# 索引
C#中修饰符用法“virtual(虚拟函数)、override(重载函数)、static(静态函数)、abstract(抽象函数)、sealed(密封函数)”
1、virtual用于修饰方法、属性、索引器或者事件声明,并使它们可以在派生类中被重写。virtual不能与static、abstract、private或者override修饰符一起使用。 声明为virtual的方法被重写时,派生类中可以使用base关键字访问父类中的publid,protected成员。
1607 0
|
C# 编译器
C#中new, override, virtual的具体用法
一句话:你是否真的了解new, override, virtual 下面代码的结果,如果基类使用接口代替,也是一样的效果。 主要注意看override或new了基类的方法后,调用方将子类对象转型为父类后的输出会有什么不同; 代码 class Program {st...
627 0
|
14天前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
29 3