面向对象的基本知识

面向对象的三大特征:

 

一、封装:

  封装是实现面向对象程序设计的第一步,封装就是将数据或函数等集合在一个个的单元中(我们称之为类)。被封装的对象通常被称为抽象数据类型。

 封装的意义:

  封装的意义在于保护或者防止代码(数据)被我们无意中破坏。在面向对象程序设计中数据被看作是一个中心的元素并且和使用它的函数结合的很密切,从而保护它不被其它的函数意外的修改。

  封装提供了一个有效的途径来保护数据不被意外的破坏。相比我们将数据(用域来实现)在程序中定义为公用的(public)我们将它们(fields)定义为私有的(privat)在很多方面会更好。私有的数据可以用两种方式来间接的控制。第一种方法,我们使用传统的存、取方法。第二种方法我们用属性(property)。

  使用属性不仅可以控制存取数据的合法性,同时也提供了“读写”、“只读”、“只写”灵活的操作方法。

 

访问修饰符:

Private:只有类本身能存取.

Protected:类和派生类可以存取.

Internal:只有同一个项目中的类可以存取.

Protected Internal:是Protected和Internal的结合.

Public:完全存取.

 

 二、继承:

 

  继承主要实现重用代码,节省开发时间。

1、C#中的继承符合下列规则:

 

继承是可传递的。如果C从B中派生,B又从A中派生,那么C不仅继承了B中声明的成员,同样也继承了A中的成员。Object类作为所有类的基类。

派生类应当是对基类的扩展。派生类可以添加新的成员,但不能除去已经继承的成员的定义。

构造函数和析构函数不能被继承。除此之外的其它成员,不论对它们定义了怎样的访问方式,都能被继承。基类中成员的访问方式只能决定派生类能否访问它们。

派生类如果定义了与继承而来的成员同名的新成员,就可以覆盖已继承的成员。但这并不因为这派生类删除了这些成员,只是不能再访问这些成员。

类可以定义虚文法、虚属性以及虚索引指示器,它的派生类能够重载这些成员,从而实现类可以展示出多态性。

  2、new关键字

 

   如果父类中声明了一个没有friend修饰的protected或public方法,子类中也声明了同名的方法。则用new可以隐藏父类中的方法。(不建议使用)

 

  3、base关键字

 

   base 关键字用于从派生类中访问基类的成员:

 

调用基类上已被其他方法重写的方法。

指定创建派生类实例时应调用的基类构造函数。

三、多态

 

  1、多态:同一操作作用于不同的对象,可以有不同的解释,产生不同的执行结果。在运行时,可以通过指向基类的指针,来调用实现派生类中的方法。

 

  编译时的多态性:

 

  编译时的多态性是通过重载来实现的。对于非虚的成员来说,系统在编译时,根据传递的参数、返回的类型等信息决定实现何种操作。

 

  运行时的多态性:

 

  运行时的多态性就是指直到系统运行时,才根据实际情况决定实现何种操作。C#中,运行时的多态性通过虚成员实现。

 

  编译时的多态性为我们提供了运行速度快的特点,而运行时的多态性则带来了高度灵活和抽象的特点。

 

   2、实现多态:

 

接口多态性。

继承多态性。

 

面向对象的基本原则

单一职责原则(SRP)  Single responsibility principle

开放封闭原则(OCP)  Open Closed Principle

里氏替换原则(LSP)   Liskov Substitution Principle

依赖倒置原则(DIP)   Dependence Inversion Principle

接口隔离原则(ISP)   Interface Segregation Principle

合成复用原则(CRP)    Composite Reuse Principle

 

单一职责原则(SRP)

•      一个类应该仅有一个引起它变化的原因(最简单,最容易理解却最不容易做到的一个设计原则)

职员类例子:

  比如在职员类里,将工程师、销售人员、销售经理这些情况都放在职员类里考虑,其结果将会非常混乱,在这个假设下,职员类里的每个方法都要if else判断是哪种情况,从类结构上来说将会十分臃肿,并且上述三种的职员类型,不论哪一种发生需求变化,都会改变职员类!这个是大家所不愿意看到的!

 

在C#项目里面:单个Control,Manager的划分,是按照单一职责原则来设计的。

 

开放封闭原则(OCP)

•      既开放又封闭,对扩展是开放的,对更改是封闭的!

•      扩展即扩展现行的模块,当我们软件的实际应用发生改变时,出现新的需求,就需要我们对模块进行扩展,使其能够满足新的需求!

 

更改封闭即是在我们对模块进行扩展时,勿需对源有程序代码和DLL进行修改或重新编译文件!

 

这个原则对我们在设计类的时候很有帮助,坚持这个原则就必须尽量考虑接口封装,抽象机制和多态技术!

 

在C#项目里面,扩展方法的特性,正好符合这个原则。对扩展开发,对修改封闭。

 

 

里氏替换原则(LSP)

•      子类可以替换父类并且出现在父类能够出现的任何地方

•      这个原则也是在贯彻GOF倡导的面向接口编程!

在这个原则中父类应尽可能使用接口或者抽象类来实现!

 

比如:WCF对外公开发契约,均是先定义接口,再做实现。符合这个原则。

 

子类通过实现了父类接口,能够替父类的使用地方!

通过这个原则,我们客户端在使用父类接口的时候,通过子类实现!

意思就是说我们依赖父类接口,在客户端声明一个父类接口,通过其子类来实现

这个时候就要求子类必须能够替换父类所出现的任何地方,这样做的好处就是,在根据新要求扩展父类接口的新子类的时候而不影响当前客户端的使用!

 

依赖倒置原则(DIP)

 传统的结构化编程中,最上层的模块通常都要依赖下面的子模块来实现,也称为高层依赖低层!

所以DIP原则就是要逆转这种依赖关系,让高层模块不要依赖低层模块,所以称之为依赖倒置原则!

 

•     高层模块不应该依赖低层模块,二者都应该依赖其抽象

•     抽象不应该依赖细节,细节应该依赖抽象

•     依赖倒置的中心思想是面向接口编程

•     依赖倒置原则是基于这样的设计理念:相对于细节的多变性,抽象的东西要稳定的多。以抽象为基础搭建的架构比以细节为基础的架构要稳定的多。在 java 中,抽象指的是接口或抽象类,细节就是具体的实现类

•     使用接口或抽象类的目的是制定好规范,而不涉及任何具体的操作,把展现细节的任务交给他们的实现类去完成

 

在C#项目里面,ORM中的顶层接口设计,再有具体类进行实现。在ORM里面便使用了这个原则。

 

ISP 接口隔离原则

•      这个原则的意思是:使用多个专门的接口比使用单个接口要好的多!

 

这个我有体会,在我实际编程中,为了减少接口的定义,将许多类似的方法都放在一个接口中,最后发现,维护和实现接口的时候花了太多精力,而接口所定义的操作相当于对客户端的一种承诺,这种承诺当然是越少越好,越精练越好,过多的承诺带来的就是你的大量精力和时间去维护!

 

合成复用原则(CRP):尽量使用对象组合,而不是继承来达到复用的目的。

 

 

通过抽象类实现的多态性。

  3、override关键字:

 

   重写父类中的virtual修饰的方法,实现多态。

posted @ 2017-01-11 23:14  苏子轩2015  阅读(131)  评论(0编辑  收藏  举报