C#通过完整的例子,Get常用的2个套路,理解抽象方法,虚方法,接口,事件

Posted dfcq

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 }
View Code

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 }
View Code

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 }
View Code
技术图片
 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 }
View Code
技术图片
 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 }
View Code
技术图片
 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 }
View Code

主程序类

技术图片
 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 }
View Code

二.抽象方法和虚方法的区别

下图中,调用虚方法MotherTongue()的时候,学生类没有重写这个方法,就调用父类的MotherTongue();老师类重写了虚方法MotherTongue,调用的时候就调用重写的方法。

目的:

1>父类的虚方法,子类想重写就重写,不行重写就算了。调用的时候,子类有重写就调用子类重写的虚方法,没有重写就调用父类虚方法。

2>父类的抽象方法,子类必须都得重写,不管子类愿不愿意,都必须重写的。技术图片

 三.理解程序封装的思想

实例化一个明星类,然后调用Show(),固定部分写死了,不固定的部分通过事件封装出去了,让用户去实现业务逻辑。

从图中可以看到,当Show()方法遇到事件的时候,就去执行用户定义的事件逻辑了,执行完用户定义的逻辑,再继续往下继续执行。

目的:

1>理解程序设计的时候,固定的部分写死,不固定部分,通过事件封装出去。

 

 技术图片

 

以上是关于C#通过完整的例子,Get常用的2个套路,理解抽象方法,虚方法,接口,事件的主要内容,如果未能解决你的问题,请参考以下文章

$.ajax 常用的套路

sql存储过程几个简单例子

sql存储过程几个简单例子

一个后端开发对Javascript 中Prototype 的一点理解

C#反射Assembly 详细说明

浅谈 C# 多态的魅力 - 虚方法抽象接口实现