重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
目录:
为北京等地区用户提供了全套网页设计制作服务,及北京网站建设行业解决方案。主营业务为成都网站制作、成都网站设计、北京网站设计,以传统方式定制建设网站,并提供域名空间备案等一条龙服务,秉承以专业、用心的态度为用户提供真诚的服务。我们深信只要达到每一位用户的要求,就会得到认可,从而选择与我们长期合作。这样,我们也可以走得更远!
【C#小知识】C#中一些易混淆概念总结--------数据类型存储位置,方法调用,out和ref参数的使用
【C#小知识】C#中一些易混淆概念总结(六)---------解析里氏替换原则,虚方法
-----------------------------------------分割线----------------------------------------------
我笔记本上C#方面的知识基本上整理的差不多了,所以这个关于《C#小知识》的系列估计就要完结了,这个过程中谢谢大家一直来对于我的支持,你们给我的宝贵的意见对我帮助很大。
在介绍抽象类和抽象方法之前还是先提一下多态的基本概念。
其实在上一篇关于里氏替换原则就已经说明了多态的精髓“子类对象可以替换父类对象的位置,而程序的功能不受影响”。还是来看一段代码吧:
////// Create By:ZhiQiang /// Create Time:2014-2-9 /// class Person { //定义虚方法以备子类重写,当子类替换父类对象的位置时,可以表现出多态 public virtual void Run() { Console.WriteLine("我是人,我会跑!"); } public virtual void Say() { Console.WriteLine("我是人,我会说话!"); } }
子类的代码如下:
//定义Teacher类继承Person class Teacher:Person { public override void Run() { Console.WriteLine("我是老师,我必须慢速跑"); } public override void Say() { Console.WriteLine("我是老师,我得说表扬的话!"); } } //定义Student类继承Person class Student : Person { //子类重写了父类的虚方法 public override void Run() { Console.WriteLine("我是学生,我会加速跑!"); } public override void Say() { Console.WriteLine("我是学生,我会说英语!"); } }
下面需要一个实现多态的类,代码如下:
//实现多态的类 class FeatureHuman { ////// 这个方法就提现了多态,当传入的是子类的对象的时候,p指向的是子类对象,就可以调用子类重写父类方法后的方法 /// /// 父类或者子类对象 public void OutPutFeature(Person p) { p.Run(); p.Say(); } }
主体代码和实现多态的方法如下:
static void Main(string[] args) { FeatureHuman fea = new FeatureHuman(); //人的特点 Person p = new Person(); Program pro = new Program(); fea.OutPutFeature(p); //学生的特点 Student s = new Student(); fea.OutPutFeature(s); //老师的特点 Teacher t = new Teacher(); fea.OutPutFeature(t); Console.ReadKey(); }
运行,打印结果如下:
这里可以发现,我们outputFeature方法根据传入的实体对象不同(父类变量指向了子类的对象),而打印出了不同人物的特点,这就是多态。
代码图解如下:
多态总结如下:
二,抽象类和抽象方法
在C#中使用abstract关键字修饰的类和方法,叫做抽象类和抽象方法。
1)抽象类中可以拥有没抽象成员,为了继承给他的子类调用 (抽象类就是为了定义抽象成员,继承给子类去实现,同时子类也可以调用父类的非抽象成员)
abstract class Person { //private int nAge; //abstract string strName; //抽象类可以包含不抽象的成员,可以给继承的子类使用 public void Say() { Console.WriteLine("我是父类,我是人!"); } public virtual void Sing() { Console.WriteLine("我是父类,我是人,我可以唱歌!"); } //Run的抽象方法 public abstract void Run(); }
2)抽象类中可以有virtual修饰的虚方法
如上面的代码,在抽象类中定义了virtual修饰的方法,编译通过。抽象类就是为了定义抽象成员,继承给子类去实现,所以子类也可以实现抽象类中的虚方法。
3)抽象类不能实例化,因为有抽象成员,而抽象成员没有方法体,如下图,
4)抽象成员不能私有,如果私有子类没有办法访问
我们可以在抽象类中定义私有成员,但是没有意义。因为子类根本访问不到这些私有成员,而抽象类本身也不能实例化,所以私有成员访问不到。
5)子类必须重写父类的抽象方法
在上面代码的基础上,我们定义一个Student类,继承抽象类,但是不实现抽象类的抽象方法,编译报错。代码如下:
6)在子类中没有办法通过base关键字调用父类抽象方法
原理同上,抽象类的抽象发放没有实现语句,就算调用也没有意义。但是可以使用base关键字调用非抽象方法,代码如下:
class Program { static void Main(string[] args) { //Person p = new Person(); Student s = new Student(); s.Run(); Console.ReadLine(); } } class Student : Person { public override void Run() { base.Say(); Console.WriteLine("我是学生,继承了父类,我可以跑!"); } }
打印结果如下:
抽象类思维导图总结如下:
抽象方法
1)抽象方法必须定义在抽象类中,
class Student : Person { public abstract void Swiming(); public override void Run() { base.Say(); Console.WriteLine("我是学生,继承了父类,我可以跑!"); } }
代码编译会报错,如下图:
2)抽象方法必须使用关键字修饰,示例代码如下:
abstract class Person { //private int nAge; //abstract string strName; //抽象类可以包含不抽象的成员,可以给继承的子类使用 public void Say() { Console.WriteLine("我是父类,我是人!"); } public virtual void Sing() { Console.WriteLine("我是父类,我是人,我可以唱歌!"); } //Run的抽象方法,不能有方法体,留给子类实现 public abstract void Run();
抽象方法思维导图总结如下:
那么什么时候使用抽象类呢?
①子类必须重写父类的方法(相当于定义了一个标准,规范)
②父类没有必要实例化,就用抽象类
③抽象类是为了继承,为了多态
最后来看一个示例代码:
定义一个抽象类,其中包含抽象方法Run()
abstract class Person {//Run的抽象方法,只要是继承我的子类都要实现这个方法 public abstract void Run(); }
分别定义两个子类,继承抽象类Person
class Student : Person { //public abstract void Swiming(); public override void Run() { // base.Say(); Console.WriteLine("我是学生,继承了父类,我可以跑!"); } } class Worker:Person { public override void Run() { Console.WriteLine("我是工人,继承了父类,我每天在厂区跑!"); } }
为了表现多态,我们编写一个方法如下:
//该方法变现了多态,根据需要返回子类的对象 public static Person GetEntity(string str) { if(str=="学生") { return new Student(); } else if(str=="工人") { return new Worker(); } return null; }
main函数中的代码如下:
static void Main(string[] args) { //不直接实例化父类对象,只是声明一个父类对象的变量来接收方法的返回值 Person p = GetEntity(Console.ReadLine()); p.Run(); Console.ReadLine(); }
运行,分别输入“工人”和“学生”的打印结果如下:
到这里这一部分的内容就结束了,希望大家多多提宝贵的意见。
如果您觉得不错,点击右下角赞一下吧!您的支持,是我写作的动力!
毕业实习交流群:221376964。你也可以关注我的新浪微博进行交流。