C#通过完整的例子,Get常用的2个套路,理解抽象方法,虚方法,接口,事件
一.理解:抽象方法,虚方法,接口,事件
描述:
1.定义一个抽象父类“People”:
要求:
1>3个属性:名字,性别,年龄;
2>一个普通方法“说话”;
3>2个抽象方法:“喜欢什么”,“会做什么”
4>1个虚方法“母语”
5>定义一个接口,用于唱歌
2.分别创建3个子类:学生,老师,校长
要求:都继承抽象类People,而且都实现唱歌接口,老师覆写虚方法“母语”
3.每个子类都有自己独有的才艺,提供一个方法功能如下:
打印“开始表演才艺”
执行具体才艺
打印“才艺表演结束,大家鼓掌!!”
意义: 抽象类,虚方法
4.定义事件
要求:
抽象类中定义一个事件,模拟“发财了”。提供一个设置金钱的方法,默认1000作为触发条件,但老师需要1,0000触发,校长需要10,0000触发
意义: 理解观察者模式,理解事件的发布/触发,事件的观察者(订户),事件的订阅
5.新增一个“明星子类”
要求:
“明星”子类中,定义三个事件:表演开始/表演高潮/表演结束;
然后新增一个Show方法: 依次调用->说话->触发表演开始事件->喜欢什么->会做什么->触发表演高潮事件->才艺->触发表演结束事件
意义:理解事件的流程封装扩展的意义
一.搭建程序
自己新建一个工程,按照下图建好框架,拷贝下面的对应类即可

People类:中有2个常用的套路
常用套路1:
封装Skill的时候,用到了套路1
★★★适用情形:子类大部分动作都相同,个别不同的情况:
父类定义一个方法Skill(),大部分相同动作放Skill中;不同的动作在父类中做成一个抽象方法或者虚方法SelfSkill(),让各个子类去实现。
常用套路2:
模拟“发财了”。提供一个设置金钱的方法,做这个的时候又套路1,2,3中方式供选择
1>小套路1:Poeplez中定义一个 虚方法SetMoney,然后子类Teacher和Schoolmaster需要重载这个虚方法,然后子类虚方法里面设置不同的金额来触发GetRich事件
2>小套路2:把金钱在People中,定义为字段 protected int Money = 1000;,然后Teacher和Schoolmaster的构造函数中,重新对这个字段赋值即可
3>小套路3:在People中,定义一个委托判断条件,protected Func<int, bool> FuncJudge = i => i > 1000;,然后Teacher和Schoolmaster的构造函数中,重写委托即可

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Security.Policy;
5 using System.Text;
6 using System.Threading.Tasks;
7
8 namespace Self.Interface
9 {
10 public abstract class People
11 {
12 //4.定义事件
13 //抽象类中定义一个事件,模拟“发财了”。提供一个设置金钱的方法,默认1000作为触发条件,但老师需要1,0000触发,校长需要10,0000触发
14 //套路:提供3中类型的套路
15 protected int Money = 1000;//套路2 把金钱做成字段,构造函数时候初始化
16 protected Func<int, bool> FuncJudge = i => i > 1000;//套路3 委托判断条件
17
18 public event Action GetRich;//发财了时间
19 public virtual void SetMoney(int monry)
20 {
21 //if (monry >= 1000)//套路1 虚方法重载
22 //if (monry >= Money)//套路2 把金钱做成字段,构造函数时候初始化
23 if (FuncJudge.Invoke(monry))//套路3 委托判断条件
24 {
25 FireGetRich();
26 }
27 }
28 /// <summary>
29 /// 触发发财了事件
30 /// </summary>
31 protected void FireGetRich()
32 {
33 GetRich?.Invoke();
34 }
35 public string Name { get; set; }
36 public string Age { get; set; }
37 public string Gender { get; set; }
38 public void Speak()
39 {
40 Console.WriteLine("我是抽象父类方法:现在我开始说话!");
41 }
42 public abstract void Like();
43 public abstract void ICanDo();
44 public virtual void MotherTongue()
45 {
46 Console.WriteLine("我是抽象类:我的母语是汉语");
47 }
48 /// <summary>
49 /// 3.每个子类都有自己独有的才艺,提供一个方法功能如下:
50 /// 打印“开始表演才艺”
51 /// 执行具体才艺
52 /// 打印“才艺表演结束,大家鼓掌!!”
53 ///
54 /// 常用的套路1:
55 /// ★★★适用情形:子类大部分动作都相同,个别不同的情况:
56 /// 父类定义一个方法Skill(),大部分相同动作放Skill中;不同的动作在父类中做成一个抽象方法或者虚方法SelfSkill(),让各个子类去实现。
57 /// </summary>
58 public void Skill()
59 {
60 Console.WriteLine("开始表演才艺");
61 this.SelfSkill();
62 Console.WriteLine("才艺表演结束,大家鼓掌!!");
63 }
64 protected abstract void SelfSkill();//这里注意 受保护的protected 和每个子类都必须实现的abstract
65 }
66 }
Sing类

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6
7 namespace Self.Interface
8 {
9 public interface ISing
10 {
11 void Sing();
12 }
13 }
4个子类

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Self.Interface;
7
8 namespace Self.Service
9 {
10 public class Schoolmaster : People, ISing
11 {
12 public Schoolmaster()
13 {
14 base.Money = 100000;//2 把金钱做成字段,构造函数时候初始化
15 FuncJudge = i => i >= 100000;//套路3 委托判断条件
16 }
17 public override void Like()
18 {
19 Console.WriteLine("我喜欢看广场舞!");
20 }
21 public override void ICanDo()
22 {
23 Console.WriteLine("我会管理学校");
24 }
25 public void Sing()
26 {
27 Console.WriteLine("开始唱:我的中国心!");
28 }
29 protected override void SelfSkill()
30 {
31 Console.WriteLine("我会拉小提琴");
32 }
33 }
34 }

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Self.Interface;
7
8 namespace Self.Service
9 {
10 public class Teacher : People, ISing
11 {
12 public Teacher()
13 {
14 base.Money = 10000;//2 把金钱做成字段,构造函数时候初始化
15 FuncJudge = (i) => i >= 10000;//套路3 委托判断条件
16 }
17 public override void Like()
18 {
19 Console.WriteLine("我喜欢科研");
20 }
21 public override void ICanDo()
22 {
23 Console.WriteLine("我可以教学");
24 }
25 public void Sing()
26 {
27 Console.WriteLine("开始唱:新贵妃醉酒!");
28 }
29 public override void MotherTongue()
30 {
31 Console.WriteLine("我是老师,我的母语是英语!");
32 }
33 protected override void SelfSkill()
34 {
35 Console.WriteLine("我会跳拉丁舞");
36 }
37 }
38 }

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Self.Interface;
7
8 namespace Self.Service
9 {
10 public class Student : People, ISing
11 {
12 public override void ICanDo()
13 {
14 Console.WriteLine("我会写作业!");
15 }
16
17 public override void Like()
18 {
19 Console.WriteLine("我喜欢打游戏");
20 }
21
22 public void Sing()
23 {
24 Console.WriteLine("开始唱:我的滑板鞋!");
25 }
26 protected override void SelfSkill()
27 {
28 Console.WriteLine("我会打王者荣耀!");
29 }
30 }
31 }

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Self.Interface;
7
8
9 namespace Self.Service
10 {
11 public class Star : People, ISing
12 {
13 public event Action StartOn;
14 public event Action HightOn;
15 public event Action EndOn;
16 /// <summary>
17 /// ★★★目的:理解事件的流程封装扩展的意义
18 ////封装框架的时候,固定的业务都封装好,开放出扩展点封装成事件;让用户自己定义逻辑。类似于事件的按钮情况
19 ///也可以理解为:程序设计的时候,固定部分写死,不固定部分通过一个事件封装出去。
20 /// </summary>
21 public void Show()
22 {
23 base.Speak();//固定部分写死
24
25 this.StartOn?.Invoke();//不固定部分,通过事件逻辑
26
27 this.Like();
28 this.ICanDo();
29
30 this.HightOn?.Invoke();
31
32 this.Sing();
33
34 this.EndOn?.Invoke();
35 }
36 public override void ICanDo()
37 {
38 Console.WriteLine("我会演戏");
39 }
40
41 public override void Like()
42 {
43 Console.WriteLine("我喜欢表演");
44 }
45
46 public void Sing()
47 {
48 Console.WriteLine("开始唱:我爱我的祖国");
49 }
50
51 protected override void SelfSkill()
52 {
53 Console.WriteLine("我一秒钟能哭出来");
54 }
55 }
56 }
主程序类

1 using System;
2 using System.Collections.Generic;
3 using System.Linq;
4 using System.Text;
5 using System.Threading.Tasks;
6 using Self.Service;
7 using Self.Interface;
8
9 namespace 自己模仿写的例子
10 {
11 class Program
12 {
13 static void Main(string[] args)
14 {
15 Console.WriteLine("********************teacher************************");
16 People teacher = new Teacher()
17 {
18 Name = "苍井空",
19 Age = "33",
20 Gender = "女",
21 };
22 teacher.GetRich += () => { Console.WriteLine("我发财了!!"); };//当设置金钱>=10000的时候,执行这个lambda表达式
23 teacher.Like();
24 teacher.ICanDo();
25 teacher.MotherTongue();
26 teacher.Skill();
27 teacher.SetMoney(10);
28 teacher.SetMoney(10000);
29 Console.WriteLine("**********************Student**********************");
30 Student student = new Student()
31 {
32 Name = "无名小辈",
33 Age = "22",
34 Gender = "男"
35 };
36 student.Like();
37 student.ICanDo();
38 student.MotherTongue();
39 student.Skill();
40 Console.WriteLine("**********************star**********************");
41 Star star = new Star()
42 {
43 Name = "颖宝宝",
44 Age = "28",
45 Gender = "女",
46 };
47 star.StartOn += () => { Console.WriteLine("主持人讲话了,大家安静了,明星即将开始表演了"); };
48 star.HightOn += () => { Console.WriteLine("主持人讲话了,明星表演的精彩吧!"); };
49 star.EndOn += () => { Console.WriteLine("主持人讲话了,明星表演结束了,大家鼓掌!!"); };
50 star.Show();
51 Console.ReadKey();
52 }
53 }
54 }
二.抽象方法和虚方法的区别
下图中,调用虚方法MotherTongue()的时候,学生类没有重写这个方法,就调用父类的MotherTongue();老师类重写了虚方法MotherTongue,调用的时候就调用重写的方法。
目的:
1>父类的虚方法,子类想重写就重写,不行重写就算了。调用的时候,子类有重写就调用子类重写的虚方法,没有重写就调用父类虚方法。
2>父类的抽象方法,子类必须都得重写,不管子类愿不愿意,都必须重写的。
三.理解程序封装的思想
实例化一个明星类,然后调用Show(),固定部分写死了,不固定的部分通过事件封装出去了,让用户去实现业务逻辑。
从图中可以看到,当Show()方法遇到事件的时候,就去执行用户定义的事件逻辑了,执行完用户定义的逻辑,再继续往下继续执行。
目的:
1>理解程序设计的时候,固定的部分写死,不固定部分,通过事件封装出去。

C#通过完整的例子,Get常用的2个套路,理解抽象方法,虚方法,接口,事件的更多相关文章
- Windows窗体应用程序常用的几个类的属性、方法以及事件
System.Diagnostics.Process 属性 public bool EnableRaisingEvents { get; set; }//获取或设置在进程终止时是否应激发 Exited ...
- 《Java从入门到失业》第四章:类和对象(4.3):一个完整的例子带你深入类和对象
4.3一个完整的例子带你深入类和对象 到此为止,我们基本掌握了类和对象的基础知识,并且还学会了String类的基本使用,下面我想用一个实际的小例子,逐步来讨论类和对象的一些其他知识点. 4.3.1需求 ...
- (转)Java中使用正则表达式的一个简单例子及常用正则分享
转自:http://www.jb51.net/article/67724.htm 这篇文章主要介绍了Java中使用正则表达式的一个简单例子及常用正则分享,本文用一个验证Email的例子讲解JAVA中如 ...
- SpringBoot整合spring-security-oauth2完整实现例子
SpringBoot整合spring-security-oauth2完整实现例子 技术栈 : springboot + spring-security + spring-oauth2 + mybati ...
- iOS开发之常用第三方框架(下载地址,使用方法,总结)
iOS开发之常用第三方框架(下载地址,使用方法,总结) 说句实话,自学了这么久iOS,如果说我不知道的但是又基本上都摸遍了iOS相关知识,但是每次做项目的时候,遇到难一点的地方或者没试过的东西就闷了. ...
- Java中常用的设计模式代码与理解
Java中常用的设计模式代码与理解 一.单例模式 1.饿汉式 (太饿了,类加载的时候就创建实例) /** * 饿汉式单例模式 */ public class HungrySingleInstance ...
- C#中常用的几种读取XML文件的方法
1.C#中常用的几种读取XML文件的方法:http://blog.csdn.net/tiemufeng1122/article/details/6723764/
- Underscore.js 常用类型判断以及一些有用的工具方法
1. 常用类型判断以及一些有用的工具方法 underscore.js 中一些 JavaScript 常用类型检查方法,以及一些工具类的判断方法. 首先我们先来谈一谈数组类型的判断.先贴出我自己封装好的 ...
- Bootstrap modal常用参数、方法和事件
Bootstrap modal(模态窗)常用参数.方法和事件: 参数: 名称 类型 默认值 描述 Backdrop Boolean或字符串“static” True True:有背景,点击modal外 ...
随机推荐
- Java — 面向对象
目录 一.类和对象 二.方法 三.封装 四.继承 五.多态 六.final 七.static 八.抽象类 九.接口 十.内部类 一.类和对象 简介:类是对事物的一种描述,对象则为具体存在的事物. 类的 ...
- 沁恒CH32V103C8T6开发环境笔记
CH32V103C8T6 CH32V103C8T6是沁恒的RISC-V内核MCU, 基于RISC-V3A处理器, 内核采用2级流水线处理,设置了静态分支预测.指令预取机制,支持DMA. 主要参数如下 ...
- 一条Sql的执行过程
一条sql内部是如何执行的: 学习MySQL实战45专栏 sql中的内部执行图: 可以分为两部分:server和存储引擎 server层包含: 连接器.分析器.优化器.执行器,涵盖了MySQL大多数核 ...
- 是时候使用 YAML 来做配置或数据文件了
概述 我们做程序,经常需要用到配置信息,回顾一下这么多年的搬砖生涯,我记得用过多种格式的文件来定义配置信息,例如 ini文件,xml文件,或者现在比较流行的 json 文件. 这些年虽然云计算和云原生 ...
- MAC系统下破解WIFI密码(亲测可用,含wifi密码字典)
出差第二天,住的小区因为疫情被封,宿舍又没有wifi,看着附近满满的WIFI信号列表,wifi万能钥匙却一个都连接不上,心中一万匹CNM...于是电脑连上手机热点,然后各种折腾,终于破解了一个隔壁的w ...
- 使用 gitbook 制作自己的 html 文档
使用 gitbook 制作自己的 html 文档 步骤如下 npm install gitbook-cli -g // 全局安装 gitbook-cli <span style="te ...
- C# 蓄水池抽样
蓄水池采样算法解决的是在给定但长度未知的大数据集中,随机等概率抽取一个数据.如果知道数据的长度,可以用随机数rand()%n得到一个确切的随机位置,或者分块取值来构造随机,那么该位置的对象就是所求的对 ...
- 基于.NetCore开发博客项目 StarBlog - (9) 图片批量导入
系列文章 基于.NetCore开发博客项目 StarBlog - (1) 为什么需要自己写一个博客? 基于.NetCore开发博客项目 StarBlog - (2) 环境准备和创建项目 基于.NetC ...
- 抽象类与接口——JavaSE基础
抽象类与接口 抽象类 抽象类既包含规范又包含具体实现 抽象类可以包含实现的方法 和 未实现的用abstract修饰的抽象方法 抽象类不可以有实例化(不能使用new实例化),只能通过子类继承,然后对子类 ...
- Jmeter基础入门应用举例
举例当然应该有接口下面以常用的百度搜索接口为例: 1.接口地址: http://www.baidu.com/s?ie=utf-8&wd=jmeter性能测试 2.请求参数 ie:编码方式,默认 ...