一.理解:抽象方法,虚方法,接口,事件

描述:

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个套路,理解抽象方法,虚方法,接口,事件的更多相关文章

  1. Windows窗体应用程序常用的几个类的属性、方法以及事件

    System.Diagnostics.Process 属性 public bool EnableRaisingEvents { get; set; }//获取或设置在进程终止时是否应激发 Exited ...

  2. 《Java从入门到失业》第四章:类和对象(4.3):一个完整的例子带你深入类和对象

    4.3一个完整的例子带你深入类和对象 到此为止,我们基本掌握了类和对象的基础知识,并且还学会了String类的基本使用,下面我想用一个实际的小例子,逐步来讨论类和对象的一些其他知识点. 4.3.1需求 ...

  3. (转)Java中使用正则表达式的一个简单例子及常用正则分享

    转自:http://www.jb51.net/article/67724.htm 这篇文章主要介绍了Java中使用正则表达式的一个简单例子及常用正则分享,本文用一个验证Email的例子讲解JAVA中如 ...

  4. SpringBoot整合spring-security-oauth2完整实现例子

    SpringBoot整合spring-security-oauth2完整实现例子 技术栈 : springboot + spring-security + spring-oauth2 + mybati ...

  5. iOS开发之常用第三方框架(下载地址,使用方法,总结)

    iOS开发之常用第三方框架(下载地址,使用方法,总结) 说句实话,自学了这么久iOS,如果说我不知道的但是又基本上都摸遍了iOS相关知识,但是每次做项目的时候,遇到难一点的地方或者没试过的东西就闷了. ...

  6. Java中常用的设计模式代码与理解

    Java中常用的设计模式代码与理解 一.单例模式 1.饿汉式 (太饿了,类加载的时候就创建实例) /** * 饿汉式单例模式 */ public class HungrySingleInstance ...

  7. C#中常用的几种读取XML文件的方法

    1.C#中常用的几种读取XML文件的方法:http://blog.csdn.net/tiemufeng1122/article/details/6723764/

  8. Underscore.js 常用类型判断以及一些有用的工具方法

    1. 常用类型判断以及一些有用的工具方法 underscore.js 中一些 JavaScript 常用类型检查方法,以及一些工具类的判断方法. 首先我们先来谈一谈数组类型的判断.先贴出我自己封装好的 ...

  9. Bootstrap modal常用参数、方法和事件

    Bootstrap modal(模态窗)常用参数.方法和事件: 参数: 名称 类型 默认值 描述 Backdrop Boolean或字符串“static” True True:有背景,点击modal外 ...

随机推荐

  1. 浅谈Java-String到底是值传递还是引用传递?

    参数传递 Java 中的参数传递分为 "值传递""引用传递" 如果你学过 C/C++应该很好理解,就是所谓的 "值传递" 和 "指 ...

  2. Spring按业务模块输出日志到不同的文件

    一.背景 在我们开发的过程中,可能存在如下情况: 1.有些时候我们需要调用第三方的接口,一般情况下,调用接口,我们都会记录请求的入参和响应的.如果我们自己系统的日志和第三方的日志混合到一个日志文件中, ...

  3. 那些我懵懵懂懂的js

    1.this 如果说this是代表当前对象,而js中,除原始值(var str = "Leonie",值Leonie是不能改变的,它就是一个字符串,如var num = 4, 4也 ...

  4. springboot处理blog字段

    springboot处理blog字段 欢迎关注博主公众号「Java大师」, 专注于分享Java领域干货文章https://www.javaman.cn/ 1.数据库表结构 其中content为long ...

  5. Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析

    Spring Ioc源码分析系列--Ioc容器BeanFactoryPostProcessor后置处理器分析 前言 上一篇文章Spring Ioc源码分析系列--Ioc源码入口分析已经介绍到Ioc容器 ...

  6. 使用VUE+SpringBoot+EasyExcel 整合导入导出数据

    使用VUE+SpringBoot+EasyExcel 整合导入导出数据 创建一个普通的maven项目即可 项目目录结构 1 前端 存放在resources/static 下 index.html &l ...

  7. 运维:OAAS

    IT和互联网运维的新篇章正要掀开,云计算和运维即服务(OaaS)正在为各类企业提供系统构建和扩展,帮助他们取得在线业务的成功. 互联网信息科技和运维一直在不断变化,包括了IT所覆盖的一切新工具.云.基 ...

  8. Python数据分析--Numpy常用函数介绍(3)

    摘要:先汇总相关股票价格,然后有选择地对其分类,再计算移动均线.布林线等. 一.汇总数据 汇总整个交易周中从周一到周五的所有数据(包括日期.开盘价.最高价.最低价.收盘价,成交量等),由于我们的数据是 ...

  9. TKE qGPU 通过 CRD 管理集群 GPU 卡资源

    作者 刘旭,腾讯云高级工程师,专注容器云原生领域,有多年大规模 Kubernetes 集群管理经验,现负责腾讯云 GPU 容器的研发工作. 背景 目前 TKE 已提供基于 qGPU 的算力/显存强隔离 ...

  10. Navicat可视化MySQL数据库

    Navicat可视化MySQL数据库 Navicat内部封装了所有的操作数据库的命令,用户只需要点击操作即可,无需书写sql语句. navicat能够充当多个数据库的客户端. 具体操作参考百度. py ...