第一节:从面向对象思想(oo)开发、接口、抽象类以及二者比较

一. 面向对象思想

1. 面向过程(OP)和面向对象(OO)的区别:

  (1):面向过程就是排着用最简单的代码一步一步写下去,没有封装,当业务复杂的时候,改动就很麻烦了

  (2):面向对象将复杂的业务分离出来几个类,然后将业务封装到类中的方法进行实现,很简洁。

2. 面向对象的三大特征

(1). 封装:将一些行为以类为单位进行包裹起来,然后通过类进行调用(如People类),可以利用private、public、protected灵活控制属性的可访问性。

好处:

  ①:保证数据安全(灵活使用private、public、protected进行控制)

  ②:屏蔽细节,只要方法名不变,可以随意扩展。

  ③:代码重用

(2). 继承:通过继承,子类可以拥有父类的一切动作(如Student类继承People类)

(3). 多态:多态有很多种。,

(补充“老杨”的经典语录:父类类型的变量可以指向子类类型的对象,调用方法的时候调用的是子类对象的实现。里氏替换原则是多态的另一种叫法,如下面的例子④)

  ①:通过不同子类继承同一个父类,实现多态(类似的还有子类继承抽象类、或者实现接口)

  ②:方法的重载本身就是一种多态

  ③:利用默认参数实现方法多态(利用命名参数实现方法的重载,即方法的多态)

  ④:运行时的多态(里氏替换原则,声明父类对象,调用虚方法,在子类覆写或者不覆写的情况下,分别调用子类方法或父类方法《只有在运行的时候才知道》)

 实体类代码:

 View Code

多态的代码:

复制代码

 1           Console.WriteLine("主要是介绍多态的各种形式");2             //1. 继承的方式实现多态,People有多种不同的实现形式(接口和抽象类的形式与之类似)3             People p1 = new People();4             People p2 = new Student();5             People p3 = new Teacher();6 7             //2. 方法的重载也是一种多态,即同名方法不同的实现形式8             Student s1 = new Student();9             s1.Show("1");
10             s1.Show(2);
11             s1.Show(1, "ypf");
12 
13             //3. 利用命名参数实现方法的重载,即方法的多态
14             Student s2 = new Student();
15             s2.play(12);
16             s2.play(12,"ypf");
17 
18             //4. 运行时的多态
19             People p4 = new Student();
20             p4.VirtualMethord1();        

复制代码

调用结果:

 

 

二. 抽象类

  抽象类是提供多个派生类共享基类的公共定义,它既可以提供抽象方法,也可以提供非抽象方法。抽象类不能实例化,必须通过继承由派生类实现其抽象方法,因此对抽象类不能使用new关键字,也不能被密封。如果派生类没有实现所有的抽象方法,则该派生类也必须声明为抽象类。另外,实现抽象方法由override方法来实现。

  抽象类的特点:

   (1). 抽象类是一个类,可以包含类的一切东西:属性、字段、委托、方法。

   (2). 抽象方法必须包含在抽象类中,抽象方法没有方法体,但抽象类中还可以包含普通的非抽象方法。

     (3). 抽象类和抽象方法的关键字均为abstract。

   (4). 继承抽象类的子类中,必须显式的覆写(override)其父类中的所有抽象方法。

     (5). 抽象类不能直接被实例化,声明的对象只能使用抽象类中已有的方法,不能使用子类新增的方法。

   (6). 同一个类只能继承唯一一个父类。

 1. 下面新建一个BasePhone类,该类中有属性、字段、委托、抽象方法、普通方法、虚方法、泛型抽象方法。

复制代码

 1   public abstract class BasePhone2     {3         //1.属性4         public string id { get; set; }5         public string name { get; set; }6         //2.字段7         public string userPwd = "maru";8         //3.委托9         public delegate void DoNothing();
10         //4.抽象方法
11         public abstract void Brand();
12         public abstract void System();
13         public abstract void Call();
14         //5.普通方法(继承的子类无法对其进行覆写,可以对其进行重写)
15         public void show()
16         {
17             Console.WriteLine("这是父类show方法");
18         }
19         //6.虚方法(可以被任何继承他的子类所覆写)
20         public virtual void ShowVirtual()
21         {
22             Console.WriteLine("这是父类showVirtual方法");
23         }
24         //7.泛型方法抽象方法
25         public abstract void Do<T>();
26     }

复制代码

 2. 新建一个iphone类,该类继承了BasePhone类,则继承了该类的属性、字段、和方法,同时必须对其抽象方法(包括泛型抽象方法)进行覆写,虚方法可以覆写也可以不进行覆写。

复制代码

 1  public class iphone : BasePhone2     {3         /// <summary>4         /// 下面四个方法为对BasePhone中四个抽象方法的覆写5         /// </summary>6         public override void Brand()7         {8             Console.WriteLine("iphone品牌");9         }
10 
11         public override void System()
12         {
13             Console.WriteLine("iphone系统");
14         }
15 
16         public override void Call()
17         {
18             Console.WriteLine("iphone电话");
19         }
20 
21         public override void Do<T>()
22         {
23             Console.WriteLine("iphone做的事情");
24         }
25         /// <summary>
26         /// 下面的ITunes方法为子类特有的方法
27         /// </summary>
28         public void ITunes()
29         {
30             Console.WriteLine("iphone连接到ITunes上");
31         }
32         /// <summary>
33         /// 下面的ShowVirtual方法覆写父类中的虚方法
34         /// </summary>
35         public override void ShowVirtual()
36         {
37             Console.WriteLine("这是子类的showVirtual方法");
38         }
39         /// <summary>
40         /// 下面的show和父类中的一模一样,但是覆盖不了
41         /// </summary>
42         public void show()
43         {
44             Console.WriteLine("这是子类中的show方法");
45         }
46     
47     }

复制代码

 3. 利用面向抽象的编程思想和里氏替换原则实例化一个iphone实例,该实例可以调用子类中4个覆写父类中的抽象方法;可以调用子类对父类虚方法覆写的方法;但对普通方法show,即使在子类中重新声明了,无论加没加new关键字(重写 ),均是调用父类的方法;该实例不能调用子类中单独新增的方法。

复制代码

 1  {2                 Console.WriteLine("------------------------------ 一.抽象类的使用和特点 ---------------------------------------");3                 //面向抽象编程4                 BasePhone iphone = new iphone();   //里氏替换原则5                 //1. iphone类中四个覆写的抽象方法6                 iphone.Brand();7                 iphone.System();8                 iphone.Call();9                 iphone.Do<iphone>();
10                 //2. BasePhone中的两个方法
11                 iphone.show();     //调用的是父类中的方法
12                 iphone.ShowVirtual();  //调用的是子类覆写以后的方法
13                 //3. 调用子类特有的方法(调用不了)
14                 // iphone.ITunes();
15 }

复制代码

结果:

  对比父类中的虚方法(virtual)和抽象方法(abstract)的区别:

    (1). 抽象方法没有方法体,其继承子类必须对其进行覆写(override).

            (2). 虚方法有方法体,其继承子类可以对其进行覆写(override),可以不进行覆写。若进行覆写,调用的则是子类中覆写后的方法;若不进行覆写,则调用的是父类     中的方法。

    (3). 抽象方法的关键字是abstract,且必须存在于抽象类中;虚方法的关键字是virtual,可以存在于任何类中。

三. 接口

  接口是包含一组虚方法的抽象类型,其中每一种方法都有其名称、参数、返回值。接口方法不能包含任何实现,CLR允许接口可以包含事件、属性、索引器、静态方法、静态字段、静态构造函数以及常数。但是接口不能包含任何静态成员。一个类可以实现多个接口,当一个类实现某个接口时,它不仅要实现该接口定义的所有方法,还要实现该接口从其他接口中继承的所有方法。

   接口的特点:

    (1). 接口不是类,里面可以包含属性、方法、事件,但不能包括字段和静态成员。

    (2). 接口只能包含没有实现的方法。

    (3). 子类实现接口,必须要实现该接口定义的所有方法,还要实现该接口从其他接口中继承的所有方法。

    (4). 接口不能被直接实例化,声明的对象只能使用接口中的方法,不能使用子类新增的方法。

    (5). 同一个类可以实现多个接口。

1. 下面新建两个接口IExtend和IPay,分别包含没有实现的方法Game和Play。

复制代码

1   public interface IExtend
2     {
3         void Game();
4     }
5    public interface IPay
6     {
7         void Play();
8     }

复制代码

2. 下面新建一个iphone子类,实现接口IExtend和IPay,则必须实现这两个接口中的所有方法。

复制代码

 1   public class iphone :  IExtend, IPay2     {3         /// <summary>4         /// 下面两个方法为显式的实现接口中的方法5         /// </summary>6         public void Play()7         {8             Console.WriteLine("这是子类显式实现了接口中的Play方法");9         }
10 
11         public void Game()
12         {
13             Console.WriteLine("这是子类显式实现了接口中的Game方法");
14         }
15     }

复制代码

3. 下面分别用面向接口编程的方式和正常方式进行调用

复制代码

 1 {2                 Console.WriteLine("------------------------------ 二.接口的使用和特点 ---------------------------------------");3                 //1.面向接口编程4                 Console.WriteLine("------------------------------ 1.面向接口编程 ---------------------------------------");5                 IExtend iphone = new iphone();   6                 iphone.Game();7                 IPay iphone2 = new iphone();8                 iphone2.Play();9                 //2.正常编程
10                 Console.WriteLine("------------------------------ 2.正常编程 ---------------------------------------");
11                 iphone iphone3 = new iphone();
12                 iphone3.Play();
13                 iphone3.Game();
14  }

复制代码

运行结果:

  

四. 抽象类和接口的比较(搜集于网络)

  (一).相同点和不同点

    相同点

      1. 都不能被直接实例化,都可以通过继承实现其抽象方法。

      2. 都是面向抽象编程的技术基础,实现了诸多的设计模式。

    不同点

      1. 接口支持多继承;抽象类不能实现多继承。

      2. 接口只能定义抽象规则;抽象类既可以定义规则,还可能提供已实现的成员。

      3. 接口是一组行为规范;抽象类是一个不完全的类,着重族的概念。

      4. 接口可以用于支持回调;抽象类不能实现回调,因为继承不支持。

      5. 接口只包含方法、属性、索引器、事件的签名,但不能定义字段和包含实现的方法;抽象类可以定义字段、属性、包含有实现的方法。

      6. 接口可以作用于值类型和引用类型;抽象类只能作用于引用类型。例如,Struct就可以继承接口,而不能继承类。

   (二).规则与场合

      1. 请记住,面向对象思想的一个最重要的原则就是:面向接口编程。

      2. 借助接口和抽象类,23个设计模式中的很多思想被巧妙的实现了,我认为其精髓简单说来就是:面向抽象编程。

      3. 抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。

      4. 接口着重于CAN-DO关系类型,而抽象类则偏重于IS-A式的关系;

      5. 接口多定义对象的行为;抽象类多定义对象的属性;

      6. 接口定义可以使用public、protected、internal 和private修饰符,但是几乎所有的接口都定义为public,原因就不必多说了。

      7. 在接口中,所有的方法都默认为public。

      8. “接口不变”,是应该考虑的重要因素。所以,在由接口增加扩展时,应该增加新的接口,而不能更改现有接口。

      9. 尽量将接口设计成功能单一的功能块,以.NET Framework为例,IDisposable、IDisposable、IComparable、IEquatable、IEnumerable等都只包含一个公共方法。

      10. 接口名称前面的大写字母“I”是一个约定,正如字段名以下划线开头一样,请坚持这些原则。

      11. 如果预计会出现版本问题,可以创建“抽象类”。例如,创建了狗(Dog)、鸡(Chicken)和鸭(Duck),那么应该考虑抽象出动物(Animal)

        来应对以后可能出现风马牛的事情。

      而向接口中添加新成员则会强制要求修改所有派生类,并重新编译,所以版本式的问题最好以抽象类来实现。

      12. 从抽象类派生的非抽象类必须包括继承的所有抽象方法和抽象访问器的实实现。

      13. 对抽象类不能使用new关键字,也不能被密封,原因是抽象类不能被实例化。

      14. 在抽象方法声明中不能使用 static 或 virtual 修饰符。

    (三). MSDN这样建议:

       1. 如果预计要创建组件的多个版本,则创建抽象类。抽象类提供简单易行的方法来控制组件版本。通过更新基类,所有继承类都随更改自动更新。

        另一方面,接口一旦创建就不能更改。如果需要接口的新版本,必须创建一个全新的接口。

       2. 如果创建的功能将在大范围的全异对象间使用,则使用接口。抽象类应主要用于关系密切的对象,而接口最适合为不相关的类提供通用功能。

       3. 如果要设计小而简练的功能块,则使用接口。如果要设计大的功能单元,则使用抽象类。

       4. 如果要在组件的所有实现间提供通用的已实现功能,则使用抽象类。抽象类允许部分实现类,而接口不包含任何成员的实现。

    (四)、经典示例

      .NET Framework中关于接口和抽象类的使用:

      集合类使用了基于接口的设计,请关注System.Collections中关于接口的设计实现;

      数据流相关类使用了基于抽象类的设计,请关注System.IO.Stream类的抽象类设计机制。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438600.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

第二节:重写(new)、覆写(overwrite)、和重载(overload)

一. 重写 1. 关键字&#xff1a;new 2. 含义&#xff1a;子类继承父类中的普通方法&#xff0c;如果在子类中重写了一个和父类中完全相同的方法&#xff0c;子类中会报警告(问是否显式的隐藏父类的中的方法)&#xff0c;如果在子类中的方法前加上new关键字&#xff0c;则警告…

java 分页查询_JavaWeb之分页查询

时间&#xff1a;2016-12-11 01:411、分页的优点&#xff1a;只查询一页&#xff0c;不需要查询所有数据&#xff0c;能够提高效率。2、分页数据页面的数据都是由Servlet传递的* 当前页&#xff1a;pageCode> 如果页面没有向Servlet传递页码&#xff0c;那么Servlet默认…

第三节:深度剖析各类数据结构(Array、List、Queue、Stack)及线程安全问题和yeild关键字

一. 各类数据结构比较及其线程安全问题 1. Array(数组)&#xff1a; 分配在连续内存中,不能随意扩展&#xff0c;数组中数值类型必须是一致的。数组的声明有两种形式&#xff1a;直接定义长度&#xff0c;然后赋值&#xff1b;直接赋值。 缺点&#xff1a;插入数据慢。 优点&a…

第四节:IO、序列化和反序列化、加密解密技术

一. IO读写   这里主要包括文件的读、写、移动、复制、删除、文件夹的创建、文件夹的删除等常规操作。 注意&#xff1a;这里需要特别注意&#xff0c;对于普通的控制台程序和Web程序&#xff0c;将"相对路径"转换成"绝对路径"的方法不一致。 (1). 在w…

java mediator_java—mediator中介模式

中介者模式是由GoF提出的23种软件设计模式的一种。Mediator模式是行为模式之一&#xff0c;Mediator模式定义:用一个中介者对象来封装一系列的对象交互。中介者使各对象不需要显式的相互引用&#xff0c;从而使其耦合松散&#xff0c;而且可以独立的改变他们之间的交互。适用性…

第五节:泛型(泛型类、接口、方法、委托、泛型约束、泛型缓存、逆变和协变)

一. 泛型诞生的背景 在介绍背景之前&#xff0c;先来看一个案例&#xff0c;要求&#xff1a;分别输出实体model1、model2、model3的id和name值,这三个实体有相同的属性名字id和name。 1 public class myUtils2 {3 //要求&#xff1a;分别输出实体model1、model2、…

第六节:反射(几种写法、好处和弊端、利用反射实现IOC)

一. 加载dll,读取相关信息 1. 加载程序集的三种方式 调用Assembly类下的三个方法&#xff1a;Load、LoadFile、LoadFrom。 1       //1.1 Load方法&#xff1a;动态默认加载当前路径下的(bin)下的dll文件,不需要后缀 2 Assembly assembly Assembly.Load(&…

第七节:语法总结(1)(自动属性、out参数、对象初始化器、var和dynamic等)

一. 语法糖简介 语法糖也译为糖衣语法&#xff0c;是由英国计算机科学家彼得约翰兰达&#xff08;Peter J. Landin&#xff09;发明的一个术语&#xff0c;指计算机语言中添加的某种语法&#xff0c;这种语法对语言的功能并没有影响&#xff0c;但是更方便程序员使用。通常来说…

java不用插件播放媒体文件_java servlet不用插件上传文件:

展开全部import java.net.*;import java.io.*;import java.util.*;import javax.servlet.*;import javax.servlet.http.*;public class SaveFileServlet extends HttpServlet{FileWriter savefile;String filename null;String value null;/*** Handles a POST request*/publ…

第八节:语法总结(2)(匿名类、匿名方法、扩展方法)

一. 匿名类 1. 传统的方式给类赋值&#xff0c;需要先建一个实体类→实例化→赋值&#xff0c;步骤很繁琐&#xff0c;在.Net 3.0时代&#xff0c;微软引入匿名类的概念&#xff0c;简化了代码编写&#xff0c;提高了开发效率。 匿名类的声明语法&#xff1a; var objnew {字段…

第九节:委托和事件(1)(委托的发展历史、插件式编程、多播委托)

一. 委托的发展历史和基本用法 说起委托&#xff0c;每个人可能都会对他有不同的理解&#xff0c;结合实战中委托的使用&#xff0c;我对其理解是&#xff1a;委托和类一样&#xff0c;是用户的一个自定义类型&#xff0c;委托可以有参数、有返回值&#xff0c;委托的关键字是d…

第十节:委托和事件(2)(泛型委托、Func和Action、事件及与委托的比较)

一. 泛型委托 所谓的泛型委托&#xff0c;即自定义委托的参数可以用泛型约束&#xff0c;同时内置委托Func和Action本身就是泛型委托。 将上一个章节中的Calculator类中的方法用自定义泛型委托重新实现一下。 1 public class Calculator22 {3 //传统解决方案一&am…

java+sm4+加密算法_SM4加密算法实现Java和C#相互加密解密

https://www.cnblogs.com/miaoziblog/p/9040473.html近期由于项目需要使用SM4对数据进行加密&#xff0c;然后传给Java后台&#xff0c;Java后台使用的也是SM4的加密算法但是就是解密不正确&#xff0c;经过一步步调试发现Java中好多数据类型与C#的相同的数据类型是存在不同的比…

DotNet进阶系列

一. 回顾历史 回顾个人发展历程&#xff0c;自2012年初次接触开发至今(2018年)已经有六个年头&#xff0c;这期间陆陆续续学习并掌握了不少技术&#xff0c;C#语言、ORM框架、多线程技术、设计模式、前端技术、MVC、MVVM框架思想等等&#xff0c;每种技术随着多次使用&#xff…

第十一节:特性(常见的特性标签、自定义特性、特性的使用案例)

一. 基本概念 1. 什么是特性? MSDN官方给出的定义时&#xff1a;公共语言运行时允许添加类似关键字的描述声明&#xff0c;叫做特性&#xff0c;它对程序中的元素进行标注&#xff0c;如类型、字段、方法和属性等。Attribute和Microsoft .Net Framework文件的元数据&#xff…

第十二节:Lambda、linq、SQL的相爱相杀(1)

一. 谈情怀 Lambda、Linq、SQL伴随着我的开发一年又一年&#xff0c;但它们三者并没有此消彼长&#xff0c;各自占有这一定的比重&#xff0c;起着不可替代的作用。 相信我们最先接触的应该就是SQL了&#xff0c;凡是科班出身的人&#xff0c;大学期间都会学习SQL Server数据库…

php java 共享session_PHP 实现多服务器共享 SESSION 数据

一、问题起源稍大一些的网站&#xff0c;通常都会有好几个服务器&#xff0c;每个服务器运行着不同功能的模块&#xff0c;使用不同的二级域名&#xff0c;而一个整体性强的网站&#xff0c;用户系统是统一的&#xff0c;即一套用户名、密码在整个网站的各个模块中都是可以登录…

第十三节:Lambda、linq、SQL的相爱相杀(2)

一. Linq开篇 1.Where用法 linq中where的用法与SQL中where的用法基本一致。 1 #region 01-where用法2 {3 //1. where用法4 //1.1 查询账号为admin的用户信息5 Console.WriteLine("------------…

第十四节:Lambda、linq、SQL的相爱相杀(3)

一. SQL 开篇 1. where用法 1    #region 封装EF调用SQL语句查询 2 public static List<T> ExecuteQuery<T>(string sql, params SqlParameter[] pars) 3 { 4 return db.Database.SqlQuery<T>(sql, pars).ToList(); 5 …

第十五节:Expression表达式目录树(与委托的区别、自行拼接、总结几类实例间的拷贝)

一. 基本介绍 回忆&#xff1a; 最早接触到表达式目录树(Expression)可能要追溯到几年前使用EF早期的时候&#xff0c;发现where方法里的参数是Expression<Func<T,bool>>这么一个类型&#xff0c;当初不是很理解&#xff0c;只是知道传入lambda表达式使用即可&…