C#语法-虚方法详解 Virtual 虚函数
本文提供全流程,中文翻译。 Chinar 坚持将简单的生活方式,带给世人! (拥有更好的阅读体验 —— 高分辨率用户请根据需求调整网页缩放比例) |
Chinar —— 心分享、心创新! 助力快速理解 虚方法 的用法 为新手节省宝贵的时间,避免采坑! |
全文高清图片,点击即可放大观看 (很多人竟然不知道)
1
Virtual Method —— 虚方法
这里我们来详细说说: 虚方法/虚函数
通过简单的例子,来说明虚方法是个什么东西
虚方法,可以理解为 “一个不完整”/“可以扩展” 的方法
Virtual (虚)与 Override (重写) 是同时出现的
在子类中,重写 Override (重写)虚方法时,父类中的函数才会被重写
在子类中,重写时,写明了 base ,并重写时,子类基于父类函数进行扩展
3个子类,同时继承一个父类
那么父类中的函数,子类都将拥有
用中国的老话 “推翻重来”理解,很是合适
加 base 后可以理解为: 老子会什么,儿子通过努力(重写),比老子会的更多/会的不一样
2
Parent Class:Enemy —— 父类:总敌人类
我们以控制台程序,来举个例子
Enemy —— 敌人类,可以包含很多种敌人的,父类/总类
我们在其中写一些,普通方法 以及 虚方法
using System; /// <summary> /// 这里明明空间用中文,便于新手理解(请不要学我) /// </summary> namespace 虚方法 { /// <summary> /// 敌人大类 /// </summary> class Enemy { /// <summary> /// 普通方法:智能系统 /// </summary> public void Ai() { Console.WriteLine("父类怪物智能系统"); Move(); } /// <summary> /// 虚方法:移动 /// </summary> public virtual void Move() { Console.WriteLine("父类怪物移动方法"); } /// <summary> /// 虚方法:打脸 /// </summary> public virtual void 打脸() { Console.WriteLine("父类打脸"); } private float hp; private float speed; public float Speed //速度 { get { return speed; } set { speed = value; } } public float Hp //血量 { get { return hp; } set { hp = value; } } } }
3
Subclass:Boss ——子类:首领
Boss —— 首领:属于怪物的一种,同样属于敌人,所以可以继承 Enemy 敌人类
new 关键字,由于子类中 Move 函数名,与父类中 Move 函数名相同
所以用 new 关键词修饰,用以区分,并隐藏父类中 Move 方法
using System; namespace 虚方法 { /// <summary> /// 首领:也属于敌人 所以继承敌人类 /// </summary> class Boss : Enemy { //子类里重写虚函数后,不论在哪里调用,都是调用重写后的 Move方法 //例如 Boss b=new Boss(); b.Ai()调用的Move方法,就是重写虚函数中 下边这个Move方法 //而不是父类中的 Move public new void Move() { Console.WriteLine("这是子类-Boss的移动方法"); } public void Attack() { Console.WriteLine("子类-Boss正在猛烈的摇晃"); Move(); } } }
4
Subclass:Enemy1、Enemy2 ——子类:敌人1、敌人2
Enemy1、Enemy2 —— 代表两种敌人类型:属于怪物的一种,同样属于敌人,所以可以继承 Enemy 敌人类
当你见到 Override 关键字,你的第一印象就应该想到,这个函数被重写了
当你见到 Override 并且,函数体中包含 base.相同的函数名,那就代表着 :这个函数是基于父类函数重写/扩展的
using System; namespace 虚方法 { /// <summary> /// 第一种敌人 /// </summary> class Enemy1 : Enemy { /// <summary> /// 这里因为没有 base,所以子类中的Move 就是下面一句代码 /// 父类中的Move,在当前类中就不存在了。因为在子类中重写了 /// </summary> public override void Move() { Console.WriteLine("这是子类-Enemy1的移动方法"); } } /// <summary> /// 第二种敌人 /// </summary> class Enemy2 : Enemy { /// <summary> /// 重写 Move 移动函数 /// </summary> public override void Move() { base.Move(); //base. —— 在原有的基础上,新增方法(也就是进行扩展,父类的函数体 依旧具备) Console.WriteLine("这是子类-Enemy2的移动方法"); //从之类往下写,就是子类新增的函数体 } } }
5
Test Main ——主入口:测试
Enemy1、Enemy2 —— 代表两种敌人类型:属于怪物的一种,同样属于敌人,所以可以继承 Enemy 敌人类
这样,不用再 Enemy1、Enemy2 类中写任何方法,默认两种怪物,就具备敌人通用的所有属性 / 函数
using System; namespace 虚方法 { /// <summary> /// 测试虚函数 /// </summary> class Program { static void Main(string[] args) { Enemy enemy = new Enemy(); enemy.Ai(); Console.WriteLine(".........................."); Enemy e = new Boss(); //敌人大类对象,用boss构造 由于子类中没有重写父类方法 e.Ai(); //所以调用的还是父类中的隐藏方法 e.Move(); Console.WriteLine(".........................."); Enemy e1 = new Enemy1(); //敌人大类对象,用子类 Enemy1 构造,由于子类中重写了父类方法 e1.Ai(); //所以调用的时候,父类的Move()方法,是子类重写一个后的方法。 e1.Move(); Console.WriteLine(".........................."); Enemy e2 = new Enemy2(); e2.Ai(); e2.Move(); Console.WriteLine(".........................."); Console.ReadLine(); } } }
输出结果:
父类怪物智能系统 父类怪物移动方法 .......................... 父类怪物智能系统 父类怪物移动方法 父类怪物移动方法 .......................... 父类怪物智能系统 这是子类-Enemy1的移动方法 这是子类-Enemy1的移动方法 .......................... 父类怪物智能系统 父类怪物移动方法 这是子类-Enemy2的移动方法 父类怪物移动方法 这是子类-Enemy2的移动方法 ..........................
支持
May Be —— 搞开发,总有一天要做的事!
拥有自己的服务器,无需再找攻略! Chinar 提供一站式教程,闭眼式创建! 为新手节省宝贵时间,避免采坑! |
先点击领取 —— 阿里全产品优惠券 (享受最低优惠)
1 —— 云服务器超全购买流程 (新手必备!)
2 —— 阿里ECS云服务器自定义配置 - 购买教程(新手必备!)
3—— Windows 服务器配置、运行、建站一条龙 !
4 —— Linux 服务器配置、运行、建站一条龙 !
Chinar
END
本博客为非营利性个人原创,除部分有明确署名的作品外,所刊登的所有作品的著作权均为本人所拥有,本人保留所有法定权利。违者必究
对于需要复制、转载、链接和传播博客文章或内容的,请及时和本博主进行联系,留言,Email: ichinar@icloud.com
对于经本博主明确授权和许可使用文章及内容的,使用时请注明文章或内容出处并注明网址
低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。
持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。
转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。
- 上一篇
Java中++,--,前缀后缀表达值的不同,与^的值计算
package 习题1; /** * ++ -- 与 ^ 的一些计算 * @author SeeClanUkyo * */ public class Test4 { public static void main(String[] args) { int i = 3; int b = (i++) + (--i) - (++i) + (i++); /** * 第一个i++为3时进行+计算,而后变为4, 第二个--i是将4递减到3, 第三个++i,3递增到了4, 第四个i++在4时进行计算,其后变为5. * * 所以3+3-4+4=6 */ System.out.println(b); ////////////////////////////// int j = 6; int k = (j++) - (--i) + (i++) - (--j); /** * 第一个j为6时进行计算,其后变为7 第二个i在上面最后为5,这时--i变为4 第三个i++在4时进行计算,其后变为5 第四个--j,变为6 * * 所以6-4+4-6=0 */ System.out.println(k); //////...
- 下一篇
java POI操作execel导出
最近项目当中在使用POI将数据填充置row和cell等行和列,最后导出成execel到前端。一开始使用的方式是一个个去赋值,但是这样做有点麻烦,代码也有点长,不太好维护。于是换了种方案,先导入固定模板,然后将要添加数据的那部分动态添加过去并且进行填充,这样做的好处有利于后期的维护和可扩展,模板可以随时换。在这过程中也学到了不少POI方面的知识。下面总结一下. HSSFWorkbook与xssfworkbook的区别:前者只支持xls(2003)的表格,后者支持xlsx(2007)的表格 我这里主要介绍HSSFWorkbook, 以下是HSSFWorkBook常用代码 Workbook workBook=new HSSFWorkbook();//工作簿 定义一个新工作簿 Sheet sheet = workBook.createSheet("第一个sheet页"); //工作表 表创建一个sheet工作表 Row row = sheet.createRow(0); //行 下标从0开始,0代表创建第一行,1代表创建第二行 Cell cell = row.createCell(0); //...
相关文章
文章评论
共有0条评论来说两句吧...
文章二维码
点击排行
推荐阅读
最新文章
- CentOS7编译安装Gcc9.2.0,解决mysql等软件编译问题
- Docker快速安装Oracle11G,搭建oracle11g学习环境
- CentOS8编译安装MySQL8.0.19
- MySQL8.0.19开启GTID主从同步CentOS8
- SpringBoot2全家桶,快速入门学习开发网站教程
- CentOS7,CentOS8安装Elasticsearch6.8.6
- CentOS8,CentOS7,CentOS6编译安装Redis5.0.7
- Red5直播服务器,属于Java语言的直播服务器
- CentOS8安装MyCat,轻松搞定数据库的读写分离、垂直分库、水平分库
- SpringBoot2整合MyBatis,连接MySql数据库做增删改查操作