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外 ...
随机推荐
- 最佳案例 | QQ 相册云原生容器化之路
关于我们 更多关于云原生的案例和知识,可关注同名[腾讯云原生]公众号~ 福利: ①公众号后台回复[手册],可获得<腾讯云原生路线图手册>&<腾讯云原生最佳实践>~ ②公 ...
- JZ009乘积小于k的子数组
title: 乘积小于k的子数组 题目描述 题目链接:乘积小于k的子数组.剑指offer009 解题思路 注意: 一开始的乘积k值就是小的,随着右边窗口移动才会不断增大 怎么样的条件才能更新左窗口:当 ...
- 206. Reverse Linked List - LeetCode
Question 206. Reverse Linked List Solution 题目大意:对一个链表进行反转 思路: Java实现: public ListNode reverseList(Li ...
- 496. Next Greater Element I - LeetCode
Question 496. Next Greater Element I Solution 题目大意:给你一个组数A里面每个元素都不相同.再给你一个数组B,元素是A的子集,问对于B中的每个元素,在A数 ...
- [codeforces] 暑期训练之打卡题(二)
每个标题都做了题目原网址的超链接 Day11<Given Length and Sum of Digits...> 题意: 给定一个数 m 和 一个长度 s,计算最大和最小在 s 长度下, ...
- 【SSM框架】Spring笔记 --- 事务详解
1.Spring的事务管理: 事务原本是数据库中的概念,在实际项目的开发中,进行事务的处理一般是在业务逻辑层, 即 Service 层.这样做是为了能够使用事务的特性来管理关联操作的业务. 在 Spr ...
- DML数据操作语言
DML数据操作语言 用来对数据库中表的数据记录进行更新.(增删改) 插入insert -- insert into 表(列名1,列名2,列名3...) values (值1,值2,值3...):向表中 ...
- Oracle数据库丢失表排查思路
Oracle数据库丢失表排查思路 说明:由于系统采用ID取模分表法进行Oracle数据存储,某日发现Oracle数据库中缺少对应的几张业务数据表,遂进行相关问题查询,简单记录一下排查思路: 由于我们代 ...
- Kubernetes Job Controller 原理和源码分析(二)
概述程序入口Job controller 的创建Controller 对象NewController()podControlEventHandlerJob AddFunc DeleteFuncJob ...
- Hive参数与性能企业级调优
Hive作为大数据平台举足轻重的框架,以其稳定性和简单易用性也成为当前构建企业级数据仓库时使用最多的框架之一. 但是如果我们只局限于会使用Hive,而不考虑性能问题,就难搭建出一个完美的数仓,所以Hi ...