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外 ...
随机推荐
- wcf使用JetEntityFrameworkProvider.dll写access数据库时,报"操作必须使用一个可更新的查询"错误的解决办法
由于users用户组无权重写access数据库,需要设置users组用户能读写access数据库.
- MySQL(8) - MySQL的事务机制
MySQL数据库的事务机制 1.1.事务的概念和特性 1.2.事务的隔离级别 repeatable read是mysql默认的事务隔离级别 #事务A #事务A,临时修改工资,未commit, STAR ...
- leetcode 643. Maximum Average Subarray I 子数组最大平均数 I
一.题目大意 https://leetcode.cn/problems/maximum-average-subarray-i/ 给你一个由 n 个元素组成的整数数组 nums 和一个整数 k . 请你 ...
- 分布式下Session一致性问题
一.Session一致性问题 1.1 什么是Session 用户使用网站的服务,基本上需要浏览器和web服务器进行多次交互,web服务器如何知道哪些请求是来自哪个会话的? 具体方式为:在会话开始时,分 ...
- Cubieboard安装系统
2013年买的一个小玩意. 一.硬件 1.1 相关资料 http://www.cubieforums.com http://cubie.cc 1.2 cubieboard1 1.3 无线网卡 水星 M ...
- 148_赠送300家门店260亿销售额的零售企业Power BI实战示例数据
焦棚子的文章目录 一背景 2022年即将到来之际,笔者准备在Power BI中做一个实战专题,作为实战专题最基础的就是demo数据,于是我们赠送大家一个300家门店,260亿+销售额,360万行+的零 ...
- Sentinel介绍与使用 收藏起来
点赞再看,养成习惯,微信搜索[牧小农]关注我获取更多资讯,风里雨里,小农等你,很高兴能够成为你的朋友. 项目源码地址:公众号回复 sentinel,即可免费获取源码 前言 在家休息的的时候,突然小勇打 ...
- 手把手教你使用Git管理你的软件代码
什么是分布式版本控制系统?Git有哪些常用命令?什么是仓库?Git的操作区域包括哪些?Git有哪些常用对象(object)?git rebase和git merge的区别是什么?git reset,g ...
- K8S 部署Dashboard UI
Kubernetes Dashboard是Kubernetes集群的通用.基于Web的UI.它允许用户管理集群中运行的应用程序并对其进行故障排除,以及管理集群本身. 访问到DashBoard有两种方式 ...
- 万字+28张图带你探秘小而美的规则引擎框架LiteFlow
大家好,今天给大家介绍一款轻量.快速.稳定可编排的组件式规则引擎框架LiteFlow. 一.LiteFlow的介绍 LiteFlow官方网站和代码仓库地址 官方网站:https://yomahub.c ...